diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 2040abd9..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,156 +0,0 @@ -# Python CircleCI 2.0 configuration file -# -# Check https://circleci.com/docs/2.0/language-python/ for more details -# -version: 2.1 - -jobs: - publish: - docker: - - image: cimg/python:3.9 - parameters: - registry_url: - description: Registry URL to upload the CLI to - type: string - default: https://upload.pypi.org/legacy/ - username: - description: Twine username - type: string - password: - description: Twine password - type: string - steps: - - checkout - - run: pip install --user --upgrade setuptools twine wheel - - run: | - python setup.py sdist bdist_wheel - twine upload --repository-url <> --username <> --password <> --verbose dist/* - -orbs: - python: circleci/python@2.1.1 - cloudsmith_ci: - jobs: - execute: - parameters: - service_name: - description: Name of the command to execute - type: string - command: - description: The command to execute - type: string - no_output_timeout: - description: Number of seconds to let job run without output before timeout - type: integer - default: 600 - is_test_suite: - description: Should the job collect test results and coverage? - type: boolean - default: false - executor: cloudsmith_executor - working_directory: ~/repo - steps: - - checkout - - restore_cache: - keys: - - v1-dependencies-{{ checksum "requirements.txt" }} - - v1-dependencies- - - run: - name: Install dependencies - command: | - python3 -m pip install uv - uv venv .venv --allow-existing - uv pip install -r requirements.txt - . .venv/bin/activate - - save_cache: - paths: - - .venv - key: v1-dependencies-{{ checksum "requirements.txt" }} - - run: - name: Run <> - command: | - . .venv/bin/activate - <> - echo $? > /tmp/run_exit_code - no_output_timeout: <> - - when: - condition: <> - steps: - - store_test_results: - path: ./reports - - store_artifacts: - path: ./reports - - executors: - cloudsmith_executor: - docker: - - image: circleci/python:3.9 - - -workflows: - commit: - jobs: - - cloudsmith_ci/execute: - name: isort - service_name: isort - command: pre-commit run -a isort - - cloudsmith_ci/execute: - name: black - service_name: black - command: pre-commit run -a black - - cloudsmith_ci/execute: - name: flake8 - service_name: flake8 - command: pre-commit run -a flake8 - - cloudsmith_ci/execute: - name: pyupgrade - service_name: pyupgrade - command: pre-commit run -a pyupgrade - - cloudsmith_ci/execute: - name: pylint - service_name: pylint - command: pylint --rcfile=.pylintrc cloudsmith_cli - no_output_timeout: 1200 - - cloudsmith_ci/execute: - name: pytest - service_name: pytest - command: pytest --junitxml ./reports/pytest.xml - is_test_suite: true - - python/test: - name: pytest-python3.10 - version: "3.10" - pkg-manager: pip - pip-dependency-file: requirements.txt - - python/test: - name: pytest-python3.11 - version: "3.11" - pkg-manager: pip - pip-dependency-file: requirements.txt - - python/test: - name: pytest-python3.12 - version: "3.12" - pkg-manager: pip - pip-dependency-file: requirements.txt - - python/test: - name: pytest-python3.13 - version: "3.13" - pkg-manager: pip - pip-dependency-file: requirements.txt - - publish: - filters: - branches: - ignore: /.*/ - tags: - only: /^v.*/ - name: cloudsmith - registry_url: https://python.cloudsmith.io/cloudsmith/cli/ - username: $CLOUDSMITH_USERNAME - password: $CLOUDSMITH_PASSWORD - - publish: - filters: - branches: - ignore: /.*/ - tags: - only: /^v.*/ - name: pypi - username: $PYPI_USERNAME - password: $PYPI_PASSWORD diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c52a94cc..188735fc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,26 +6,35 @@ on: - "v*" permissions: - id-token: write - contents: write + id-token: write + contents: write + jobs: + # Build and publish to GitHub, Cloudsmith (zipapp + Docker) build: + name: Build and publish artifacts runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Set up Python 3.11 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 + cache: 'pip' + - name: Install dependencies run: | python -m pip install --upgrade pip pip install shiv + - name: Get version id: get_version run: echo "VERSION=$(cat cloudsmith_cli/data/VERSION)" >> $GITHUB_ENV + - name: Create Zipapp run: shiv -o cloudsmith-${{ env.VERSION }}.pyz -c cloudsmith . + - name: Create Release id: create_release uses: actions/create-release@v1 @@ -36,6 +45,7 @@ jobs: release_name: Release v${{ env.VERSION }} draft: false prerelease: false + - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 @@ -46,26 +56,68 @@ jobs: asset_path: ./cloudsmith-${{ env.VERSION }}.pyz asset_name: cloudsmith-${{ env.VERSION }}.pyz asset_content_type: application/zip + - name: Install and authenticate Cloudsmith CLI - uses: cloudsmith-io/cloudsmith-cli-action@v1.0.3 + uses: cloudsmith-io/cloudsmith-cli-action@v1 with: oidc-namespace: ${{ vars.CLOUDSMITH_NAMESPACE }} oidc-service-slug: ${{ vars.CLOUDSMITH_SVC_SLUG }} + - name: Push Zipapp to Cloudsmith id: push_zipapp run: cloudsmith push raw ${{ vars.CLOUDSMITH_NAMESPACE }}/cli-zipapp ./cloudsmith-${{ env.VERSION }}.pyz --name cloudsmith-cli --version ${{ env.VERSION }} + + - name: Install build dependencies for Python packages + run: pip install setuptools wheel + + - name: Build Python packages + run: python setup.py sdist bdist_wheel + + - name: Push source distribution to Cloudsmith + run: cloudsmith push python ${{ vars.CLOUDSMITH_NAMESPACE }}/cli dist/cloudsmith-cli-${{ env.VERSION }}.tar.gz + + - name: Push wheel to Cloudsmith + run: cloudsmith push python ${{ vars.CLOUDSMITH_NAMESPACE }}/cli dist/cloudsmith_cli-${{ env.VERSION }}-py3-none-any.whl + - name: Build Docker image id: build_cli_image run: | docker build --build-arg CLOUDSMITH_CLI_VERSION=${{ env.VERSION }} -t docker.cloudsmith.io/${{ vars.CLOUDSMITH_NAMESPACE }}/cli-zipapp/cloudsmith-cli:${{ env.VERSION }} . + - name: Push Dockerised CLI to Cloudsmith id: push_dockerised_cli_cloudsmith run: | echo "${CLOUDSMITH_API_KEY}" | docker login docker.cloudsmith.io -u ${{ vars.CLOUDSMITH_SVC_SLUG }} --password-stdin docker push docker.cloudsmith.io/${{ vars.CLOUDSMITH_NAMESPACE }}/cli-zipapp/cloudsmith-cli:${{ env.VERSION }} + - name: Push Dockerised CLI to DockerHub id: push_dockerised_cli_dockerhub run: | docker tag docker.cloudsmith.io/${{ vars.CLOUDSMITH_NAMESPACE }}/cli-zipapp/cloudsmith-cli:${{ env.VERSION }} cloudsmith/cloudsmith-cli:${{ env.VERSION }} echo "${{ secrets.DOCKERHUB_PAT }}" | docker login -u ${{ vars.DOCKERHUB_USER }} --password-stdin docker push cloudsmith/cloudsmith-cli:${{ env.VERSION }} + + # Publish Python packages to PyPI + publish-pypi: + name: Publish to PyPI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: 3.11 + + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel + + - name: Build packages + run: python setup.py sdist bdist_wheel + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..ede0356d --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,198 @@ +name: Test + +on: + push: + branches: + - '**' + pull_request: + branches: + - '**' + +permissions: + contents: read + +jobs: + # Linting jobs run in parallel + isort: + name: Check import sorting (isort) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + cache-dependency-path: requirements.txt + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run isort + run: pre-commit run -a isort + + black: + name: Check code formatting (black) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + cache-dependency-path: requirements.txt + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run black + run: pre-commit run -a black + + flake8: + name: Check code style (flake8) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + cache-dependency-path: requirements.txt + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run flake8 + run: pre-commit run -a flake8 + + pyupgrade: + name: Check for Python upgrades (pyupgrade) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + cache-dependency-path: requirements.txt + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run pyupgrade + run: pre-commit run -a pyupgrade + + pylint: + name: Run comprehensive linting (pylint) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + cache-dependency-path: requirements.txt + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run pylint + run: pylint --rcfile=.pylintrc cloudsmith_cli + + # Test jobs run across Python versions + pytest: + name: Run tests (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + + 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' + cache-dependency-path: requirements.txt + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Install package + run: pip install -e . + + - name: Run pytest + env: + PYTEST_CLOUDSMITH_API_KEY: ${{ secrets.PYTEST_CLOUDSMITH_API_KEY }} + PYTEST_CLOUDSMITH_API_HOST: ${{ vars.PYTEST_CLOUDSMITH_API_HOST }} + PYTEST_CLOUDSMITH_ORGANIZATION: ${{ vars.PYTEST_CLOUDSMITH_ORGANIZATION }} + run: pytest --junitxml=./reports/pytest.xml + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ matrix.python-version }} + path: ./reports/pytest.xml + retention-days: 30 + + # Test zipapp build across Python versions + test-zipapp-build: + name: Test zipapp build (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + + 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 shiv + run: pip install shiv + + - name: Get version + id: get_version + run: echo "VERSION=$(cat cloudsmith_cli/data/VERSION)" >> $GITHUB_ENV + + - name: Create Zipapp + run: shiv -o cloudsmith-${{ env.VERSION }}.pyz -c cloudsmith . + + - name: Make executable + run: chmod +x cloudsmith-${{ env.VERSION }}.pyz + + - name: Validate zipapp execution + run: | + OUTPUT=$(./cloudsmith-${{ env.VERSION }}.pyz --version) + echo "Zipapp Version: $OUTPUT" + echo "$OUTPUT" | grep "${{ env.VERSION }}" diff --git a/.pylintrc b/.pylintrc index d0167a24..9d1dbb02 100644 --- a/.pylintrc +++ b/.pylintrc @@ -88,7 +88,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.9 +py-version=3.10 # Discover python modules and packages in the file system subtree. recursive=no diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d01e31c..d0b61d78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,18 +7,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] -### Fixed - -- Upgraded `urllib3` from `v1.26.20` to `v2.5.0`. -- Added `mock_keyring` fixture to prevent SSO token refresh attempts during individual `test_rest.py` test which runs in pipelines (full suite passes). Caused by [HTTPretty issue 484](https://github.com/gabrielfalcao/HTTPretty/issues/484). -- Entitlement token list command now fixed - ### Added +- Migrate from CircleCI to GitHub Actions for testing and release workflows. +- Remove CircleCi workflows. - Set `--show-all` to alias `--page-all` - Add the ability to use a shortcut within `--page-size` to use pass `-1` or `*` to retrieve all pages i.e. `--page-size -1` or `--page-size *` (note the wildcard may require escaping in some shell environments) - Added support for deny policy management commands (list, create, get, update, delete) +### Fixed + +- Upgraded `urllib3` from `v1.26.20` to `v2.5.0`. +- Added `mock_keyring` fixture to prevent SSO token refresh attempts during individual `test_rest.py` test which runs in pipelines (full suite passes). Caused by [HTTPretty issue 484](https://github.com/gabrielfalcao/HTTPretty/issues/484). +- Entitlement token list command now fixed + ## [1.9.4] - 2025-11-07 > No code changes in this release. Version bump performed for release process consistency and to address packaging/metadata updates. diff --git a/setup.py b/setup.py index 15b20633..bcc73c7a 100644 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ def get_long_description(): include_package_data=True, zip_safe=False, platforms=["any"], - python_requires=">=3.9.0", + python_requires=">=3.10.0", install_requires=[ "click>=8.2.0,!=8.3.0", "click-configfile>=0.2.3", @@ -79,7 +79,6 @@ def get_long_description(): "License :: OSI Approved :: Apache Software License", "Operating System :: POSIX :: Linux", "Programming Language :: Python", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12",