diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f794515 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,44 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + 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 + with: + 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 }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3ed7fb3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,54 @@ +name: Release + +on: + push: + branches: [main] + workflow_dispatch: + +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: 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 + prerelease: ${{ github.event_name == 'push' }} diff --git a/CI-CD.md b/CI-CD.md new file mode 100644 index 0000000..bbb2774 --- /dev/null +++ b/CI-CD.md @@ -0,0 +1,38 @@ +# 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 manually via **Actions → Release → Run workflow** in GitHub. + +**Version format:** `YYYY.MM.DD.` — for example, `2026.04.15.42` + +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. 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:** + +Go to the repository on GitHub → Actions → Release → Run workflow → Run workflow. + +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/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, diff --git a/pyproject.toml b/pyproject.toml index cf06db5..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" @@ -33,9 +33,12 @@ dev = [ "pytest-mock>=3", "pytest-recording>=0.13", "vcrpy>=6", + "python-dotenv>=1", "tox>=4", ] +[tool.setuptools_scm] + [tool.setuptools.packages.find] where = ["."] include = ["ce*"] @@ -64,6 +67,7 @@ deps = pytest-mock>=3 pytest-recording>=0.13 vcrpy>=6 + python-dotenv>=1 commands_pre = pip install -e .