From afd4e29db807a2ea73463de61bd89ac35c4c7b7f Mon Sep 17 00:00:00 2001 From: Omar Adel Date: Mon, 10 Aug 2026 00:21:15 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(projects):=20auto-generate?= =?UTF-8?q?=20identifier=20on=20project=20create?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `project new ` without `-i` previously sent CreateProject with no identifier, which the Plane API rejects. - Add _default_identifier helper: derives identifier from the project name (first 5 alphanumeric chars, uppercased). - Explicit -i flag still takes precedence; create now always sends an identifier. - Add tests/test_projects.py covering derivation, punctuation stripping, short names, and uppercasing. --- src/planecli/commands/projects.py | 10 +++++++--- tests/test_projects.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 tests/test_projects.py diff --git a/src/planecli/commands/projects.py b/src/planecli/commands/projects.py index e0fddda..83f335a 100644 --- a/src/planecli/commands/projects.py +++ b/src/planecli/commands/projects.py @@ -36,6 +36,11 @@ } +def _default_identifier(name: str) -> str: + """Derive a default project identifier from the project name.""" + return "".join(c for c in name if c.isalnum())[:5].upper() + + def _enrich_project(data: dict) -> dict: """Add convenience fields to a project dict.""" network = data.get("network") @@ -157,9 +162,8 @@ async def create( client = get_client() workspace = get_workspace() - create_data = CreateProject(name=name) - if identifier: - create_data.identifier = identifier.upper() + resolved_identifier = (identifier or _default_identifier(name)).upper() + create_data = CreateProject(name=name, identifier=resolved_identifier) if description: create_data.description = description diff --git a/tests/test_projects.py b/tests/test_projects.py new file mode 100644 index 0000000..bbca584 --- /dev/null +++ b/tests/test_projects.py @@ -0,0 +1,19 @@ +"""Tests for the project commands module.""" + +from __future__ import annotations + +from planecli.commands.projects import _default_identifier + + +class TestDefaultIdentifier: + def test_derives_from_name(self): + assert _default_identifier("Frontend App") == "FRONT" + + def test_strips_punctuation(self): + assert _default_identifier("My Backend API!") == "MYBAC" + + def test_keeps_short_name(self): + assert _default_identifier("FE") == "FE" + + def test_uppercases(self): + assert _default_identifier("backend") == "BACKE"