From b8dd40071d0205e5e8c4a85ddeb938f742802436 Mon Sep 17 00:00:00 2001 From: Ariel Rolfo Date: Mon, 13 Apr 2026 19:21:35 -0300 Subject: [PATCH 1/6] Add CI pipeline for unit tests Adds GitHub Actions CI workflow that runs unit tests across Python 3.10/3.11/3.12 on push and PR to main. Also adds missing python-dotenv dev dependency used by the test suite. Closes #70 --- .github/workflows/ci.yml | 31 +++++++++++++++++++++++++++++++ pyproject.toml | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cb8687d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + name: Unit tests (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: pip + + - name: Install tox + run: pip install tox + + - name: Run unit tests + run: tox -e unit diff --git a/pyproject.toml b/pyproject.toml index cf06db5..38756c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ dev = [ "pytest-mock>=3", "pytest-recording>=0.13", "vcrpy>=6", + "python-dotenv>=1", "tox>=4", ] @@ -64,6 +65,7 @@ deps = pytest-mock>=3 pytest-recording>=0.13 vcrpy>=6 + python-dotenv>=1 commands_pre = pip install -e . From 8282b6b0da56bd98fe963b55790f43db2dba883b Mon Sep 17 00:00:00 2001 From: Ariel Rolfo Date: Mon, 13 Apr 2026 19:30:50 -0300 Subject: [PATCH 2/6] Simplify CI to single Python 3.13 version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an internal tool — no need to test across multiple versions. --- .github/workflows/ci.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb8687d..6337bb3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,18 +10,13 @@ jobs: test: name: Unit tests (Python ${{ matrix.python-version }}) runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.10", "3.11", "3.12"] - steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python 3.13 uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: "3.13" cache: pip - name: Install tox From ae12a7fa9026f72e2f2f8869189b73e9f82d4723 Mon Sep 17 00:00:00 2001 From: Ariel Rolfo Date: Mon, 13 Apr 2026 19:47:31 -0300 Subject: [PATCH 3/6] Add release pipeline, CI-CD docs, and install guide - Adds GitHub Actions release workflow triggered by version tags (v*.*.*) - Switches version management to setuptools-scm (version derived from git tag) - Adds CI-CD.md documenting how CI and the release process work - Adds INSTALL.md with end-user installation instructions Closes #70 --- .github/workflows/release.yml | 39 +++++++++++++++++++++++++++++++++++ CI-CD.md | 39 +++++++++++++++++++++++++++++++++++ INSTALL.md | 35 +++++++++++++++++++++++++++++++ pyproject.toml | 6 ++++-- 4 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 CI-CD.md create mode 100644 INSTALL.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b409d12 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,39 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" + +jobs: + release: + name: Build and release + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + cache: pip + + - name: Install tox and build + run: pip install tox build + + - name: Run unit tests + run: tox -e unit + + - name: Build package + run: python -m build + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: dist/* + generate_release_notes: true diff --git a/CI-CD.md b/CI-CD.md new file mode 100644 index 0000000..8007ac2 --- /dev/null +++ b/CI-CD.md @@ -0,0 +1,39 @@ +# CI/CD + +## CI pipeline + +The CI pipeline runs automatically on every push to `main` and on every pull request targeting `main`. + +**What it does:** +- Sets up Python 3.13 +- Installs `tox` +- Runs unit tests via `tox -e unit` + +Integration tests (those marked `@pytest.mark.integration`) are excluded from CI because they require a live API environment. + +To run tests locally: +``` +pip install tox +tox -e unit +``` + +## Release pipeline + +Releases are triggered by pushing a version tag to `main`. + +**Tag format:** `vMAJOR.MINOR.PATCH` — for example, `v1.2.0` + +The version number is read automatically from the git tag via `setuptools-scm` — there is no version field to manually edit. + +**What the pipeline does:** +1. Runs unit tests — if they fail, the release is aborted +2. Builds the package (`.whl` and `.tar.gz`) +3. Creates a GitHub Release with both files attached and auto-generated release notes + +**How to cut a release:** +``` +git tag v1.2.0 +git push origin v1.2.0 +``` + +That's it. The pipeline takes care of the rest. diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..4f5f01b --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,35 @@ +# Installation + +## Requirements + +- Python 3.10 or later +- `pip` + +## Install from a release + +1. Go to the [Releases page](../../releases) and download the `.whl` file from the latest release. + +2. Install it with pip: +``` +pip install ce_cli--py3-none-any.whl +``` + +3. Verify the installation: +``` +ce --help +``` + +## Install from source + +``` +git clone https://github.com/CredentialEngine/ce-cli.git +cd ce-cli +pip install -e . +``` + +## Upgrading + +Download the `.whl` from the new release and re-run: +``` +pip install --upgrade ce_cli--py3-none-any.whl +``` diff --git a/pyproject.toml b/pyproject.toml index 38756c9..bb08ebc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [build-system] -requires = ["setuptools>=68", "wheel"] +requires = ["setuptools>=68", "setuptools-scm>=8", "wheel"] build-backend = "setuptools.build_meta" [project] name = "ce-cli" -version = "0.1.0" +dynamic = ["version"] description = "Credential Engine CLI - Internal platform management tool" readme = "README.md" requires-python = ">=3.10" @@ -37,6 +37,8 @@ dev = [ "tox>=4", ] +[tool.setuptools_scm] + [tool.setuptools.packages.find] where = ["."] include = ["ce*"] From 2234ad874c1a82a863fdac9e454d9216f45999e8 Mon Sep 17 00:00:00 2001 From: Ariel Rolfo Date: Tue, 14 Apr 2026 20:39:35 -0300 Subject: [PATCH 4/6] Pass repository secrets to CI unit test environment Wires GitHub secrets as env vars so tests that depend on CE_TEST_* values can run in CI. --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6337bb3..d913812 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,3 +24,10 @@ jobs: - name: Run unit tests run: tox -e unit + env: + CE_PUBLISHER_BASE: ${{ secrets.CE_PUBLISHER_BASE }} + CE_TEST_ACCESS_TOKEN: ${{ secrets.CE_TEST_ACCESS_TOKEN }} + CE_TEST_USER_ID: ${{ secrets.CE_TEST_USER_ID }} + CE_TEST_CTID: ${{ secrets.CE_TEST_CTID }} + CE_TEST_CHALLENGE_UUID: ${{ secrets.CE_TEST_CHALLENGE_UUID }} + CE_TEST_DID_KEY: ${{ secrets.CE_TEST_DID_KEY }} From bf2cbaf93a7269e7d6060ccfcceae72b5498da23 Mon Sep 17 00:00:00 2001 From: Ariel Rolfo Date: Wed, 15 Apr 2026 08:20:06 -0300 Subject: [PATCH 5/6] Use date-based versioning and embed version in every build - Version format: YYYY.MM.DD. (e.g. 2026.04.15.42) - Both CI and Release pipelines now generate the version dynamically and pass it to the build via SETUPTOOLS_SCM_PRETEND_VERSION - Release now triggered via workflow_dispatch instead of git tags - CI now includes a build step to verify the package builds on every run - Updates CI-CD.md to reflect the new release process --- .github/workflows/ci.yml | 17 ++++++++++++++--- .github/workflows/release.yml | 18 +++++++++++++++--- CI-CD.md | 19 +++++++++---------- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d913812..f794515 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,10 +8,13 @@ on: jobs: test: - name: Unit tests (Python ${{ matrix.python-version }}) + name: Unit tests runs-on: ubuntu-latest + steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python 3.13 uses: actions/setup-python@v5 @@ -19,8 +22,11 @@ jobs: python-version: "3.13" cache: pip - - name: Install tox - run: pip install tox + - name: Generate version + run: echo "VERSION=$(date +%Y.%m.%d).${{ github.run_number }}" >> $GITHUB_ENV + + - name: Install tox and build + run: pip install tox build - name: Run unit tests run: tox -e unit @@ -31,3 +37,8 @@ jobs: CE_TEST_CTID: ${{ secrets.CE_TEST_CTID }} CE_TEST_CHALLENGE_UUID: ${{ secrets.CE_TEST_CHALLENGE_UUID }} CE_TEST_DID_KEY: ${{ secrets.CE_TEST_DID_KEY }} + + - name: Build package + run: python -m build + env: + SETUPTOOLS_SCM_PRETEND_VERSION: ${{ env.VERSION }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b409d12..2787e53 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,7 @@ name: Release on: - push: - tags: - - "v*.*.*" + workflow_dispatch: jobs: release: @@ -23,17 +21,31 @@ jobs: python-version: "3.13" cache: pip + - name: Generate version + run: echo "VERSION=$(date +%Y.%m.%d).${{ github.run_number }}" >> $GITHUB_ENV + - name: Install tox and build run: pip install tox build - name: Run unit tests run: tox -e unit + env: + CE_PUBLISHER_BASE: ${{ secrets.CE_PUBLISHER_BASE }} + CE_TEST_ACCESS_TOKEN: ${{ secrets.CE_TEST_ACCESS_TOKEN }} + CE_TEST_USER_ID: ${{ secrets.CE_TEST_USER_ID }} + CE_TEST_CTID: ${{ secrets.CE_TEST_CTID }} + CE_TEST_CHALLENGE_UUID: ${{ secrets.CE_TEST_CHALLENGE_UUID }} + CE_TEST_DID_KEY: ${{ secrets.CE_TEST_DID_KEY }} - name: Build package run: python -m build + env: + SETUPTOOLS_SCM_PRETEND_VERSION: ${{ env.VERSION }} - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: + tag_name: v${{ env.VERSION }} + name: v${{ env.VERSION }} files: dist/* generate_release_notes: true diff --git a/CI-CD.md b/CI-CD.md index 8007ac2..bbb2774 100644 --- a/CI-CD.md +++ b/CI-CD.md @@ -19,21 +19,20 @@ tox -e unit ## Release pipeline -Releases are triggered by pushing a version tag to `main`. +Releases are triggered manually via **Actions → Release → Run workflow** in GitHub. -**Tag format:** `vMAJOR.MINOR.PATCH` — for example, `v1.2.0` +**Version format:** `YYYY.MM.DD.` — for example, `2026.04.15.42` -The version number is read automatically from the git tag via `setuptools-scm` — there is no version field to manually edit. +The version is auto-generated from the date and the pipeline run number. There is no version field to manually edit and no tags to push. **What the pipeline does:** -1. Runs unit tests — if they fail, the release is aborted -2. Builds the package (`.whl` and `.tar.gz`) -3. Creates a GitHub Release with both files attached and auto-generated release notes +1. Generates the version from the current date and run number +2. Runs unit tests — if they fail, the release is aborted +3. Builds the package (`.whl` and `.tar.gz`) with the generated version embedded +4. Creates a GitHub Release tagged `v` with both files attached and auto-generated release notes **How to cut a release:** -``` -git tag v1.2.0 -git push origin v1.2.0 -``` + +Go to the repository on GitHub → Actions → Release → Run workflow → Run workflow. That's it. The pipeline takes care of the rest. From 025cd19985f56ab61ae3734dd44c1af31d36bedd Mon Sep 17 00:00:00 2001 From: Ariel Rolfo Date: Thu, 16 Apr 2026 09:19:22 -0300 Subject: [PATCH 6/6] Dynamic version from package metadata and promote release pipeline - Read __version__ via importlib.metadata at runtime so ce --version and ce version reflect the build-injected version - Release pipeline now auto-triggers on push to main (pre-release) and supports manual workflow_dispatch for stable promotion --- .github/workflows/release.yml | 3 +++ ce/__init__.py | 7 ++++++- ce/main.py | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2787e53..3ed7fb3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,8 @@ name: Release on: + push: + branches: [main] workflow_dispatch: jobs: @@ -49,3 +51,4 @@ jobs: name: v${{ env.VERSION }} files: dist/* generate_release_notes: true + prerelease: ${{ github.event_name == 'push' }} diff --git a/ce/__init__.py b/ce/__init__.py index a68927d..de1ea64 100644 --- a/ce/__init__.py +++ b/ce/__init__.py @@ -1 +1,6 @@ -__version__ = "0.1.0" \ No newline at end of file +from importlib.metadata import version, PackageNotFoundError + +try: + __version__ = version("ce-cli") +except PackageNotFoundError: + __version__ = "0.0.0+unknown" \ No newline at end of file diff --git a/ce/main.py b/ce/main.py index db488fd..b54b44a 100644 --- a/ce/main.py +++ b/ce/main.py @@ -9,6 +9,7 @@ import click from rich.console import Console +from ce import __version__ from ce.commands.auth import auth_group from ce.commands.env import env_group from ce.commands.iir import iir_group @@ -20,7 +21,7 @@ @click.group(context_settings=CONTEXT_SETTINGS) -@click.version_option(version="0.1.0", prog_name="ce") +@click.version_option(version=__version__, prog_name="ce") @click.option( "--debug", is_flag=True,