-
Notifications
You must be signed in to change notification settings - Fork 165
Migrate to uv and integrate PSR for automated releases #218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
1717e4c
599170d
708e245
0b57c82
c6e8807
5141c5d
02278d5
3c496a9
d0494b7
8dd5a29
f981996
6e075c2
35c6552
634f249
abd4a7b
1e77de2
5a28257
3d43662
61f4ffd
bb955b9
8982a9f
c9ebd39
a808ca5
10b1dfb
1a04175
088f445
46e9493
3a49500
7912993
5797a2f
b14107c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| pull_request: | ||
| branches: [main] | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| commitlint: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ["3.11"] # TODO see https://github.com/mitre-attack/mitreattack-python/issues/176 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Install the latest version of uv | ||
| uses: astral-sh/setup-uv@v7 | ||
| with: | ||
| version: "latest" | ||
|
|
||
| - name: Set up Python | ||
| run: uv python install ${{ matrix.python-version }} | ||
|
|
||
| - name: Install dependencies | ||
| run: uv sync --all-extras | ||
|
|
||
| - name: Check commit messages | ||
| run: | | ||
| if [ "${{ github.event_name }}" = "pull_request" ]; then | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to make sure we make it as easy as possible for external contributors to contribute. This makes me think of this FAQ from the Conventional Commits site.
I think it might be better to squash commits from pull requests somehow instead and only validate commit messages that we ourselves write, to not make it an overly arduous process for external contribs.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great idea. Just pushed a change to (hopefully) enable this: # For PRs, validate the PR title (which becomes the squash commit message).
# This avoids burdening external contributors with conventional commit enforcement
# on every individual commit. See: https://www.conventionalcommits.org/en/v1.0.0/
#
# For pushes to main, validate the final commit message (the squash merge commit)
# using commitizen as a safety net.
commitlint:
runs-on: ubuntu-latest
steps:
# PR: validate PR title follows conventional commit format
- name: Validate PR title
if: github.event_name == 'pull_request'
uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# For work-in-progress PRs you can typically use draft pull requests from GitHub.
# This action allows us to use the special "[WIP]" prefix to indicate a draft state
# without actually flagging the PR as a draft.
# Example:
# `[WIP] feat: Add support for Node.js 18` <--- will not be validated!
wip: true
# Push to main: validate the squash merge commit message directly
- name: Checkout
if: github.event_name == 'push'
uses: actions/checkout@v6
with:
fetch-depth: 2
- name: Install uv
if: github.event_name == 'push'
uses: astral-sh/setup-uv@v7
with:
version: "latest"
- name: Install Python and dependencies
if: github.event_name == 'push'
run: |
uv python install 3.11
uv sync --all-extras
- name: Validate commit message
if: github.event_name == 'push'
run: uv run cz check --rev-range HEAD~1..HEADThe first step uses an off the shelf GH action, amannn/action-semantic-pull-request@v5 to ensure that the pull request title match the Conventional Commits spec. It only runs on The latter four steps run on We'll probably want to configure the repo to only allow squash merges (or at least default to them):
This will ensure the conventional PR title always becomes the merge commit message that PSR parses. (We'll of course need to test this.) |
||
| uv run cz check --rev-range origin/${{ github.base_ref }}..HEAD | ||
| else | ||
| uv run cz check --rev-range HEAD~1..HEAD | ||
| fi | ||
|
|
||
| lint: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ["3.11"] # TODO see https://github.com/mitre-attack/mitreattack-python/issues/176 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
|
|
||
| - name: Install the latest version of uv | ||
| uses: astral-sh/setup-uv@v7 | ||
| with: | ||
| version: "latest" | ||
|
|
||
| - name: Set up Python | ||
| run: uv python install ${{ matrix.python-version }} | ||
|
|
||
|
seansica marked this conversation as resolved.
|
||
| - name: Install dependencies | ||
| run: uv sync --all-extras | ||
|
|
||
| - name: Lint with ruff | ||
| run: uv run ruff check --output-format github | ||
|
|
||
| - name: Check formatting with ruff | ||
| run: uv run ruff format --check | ||
|
|
||
| test: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ["3.11"] # TODO see https://github.com/mitre-attack/mitreattack-python/issues/176 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
|
|
||
| - name: Install the latest version of uv | ||
| uses: astral-sh/setup-uv@v7 | ||
| with: | ||
| version: "latest" | ||
|
|
||
| - name: Set up Python | ||
| run: uv python install ${{ matrix.python-version }} | ||
|
|
||
|
seansica marked this conversation as resolved.
|
||
| - name: Install dependencies | ||
| run: uv sync --all-extras | ||
|
|
||
| - name: Run pytest | ||
| run: uv run pytest --cov=mitreattack | ||
|
|
||
| release: | ||
| needs: [commitlint, lint, test] | ||
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||
| strategy: | ||
| matrix: | ||
| python-version: ["3.11"] # TODO see https://github.com/mitre-attack/mitreattack-python/issues/176 | ||
| runs-on: ubuntu-latest | ||
| # The concurrency block prevents multiple release jobs from running simultaneously for the same branch. | ||
| # This is particularly useful for releases since you typically want sequential deployments (finish | ||
| # current release before starting next) rather than canceling in-progress releases or running them | ||
| # in parallel. | ||
| concurrency: | ||
| # Creates a concurrency group keyed by workflow name + "release" + branch name (e.g., "Continuous Delivery-release-main") | ||
| group: ${{ github.workflow }}-release-${{ github.ref_name }} | ||
| # If a release is already running and a new push triggers another, the new job waits rather than canceling the running one | ||
| # If you changed cancel-in-progress to true, a new push would cancel the currently running release job. | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| steps: | ||
| # Note: We checkout the repository at the branch that triggered the workflow. | ||
| # Python Semantic Release will automatically convert shallow clones to full clones | ||
| # if needed to ensure proper history evaluation. However, we forcefully reset the | ||
| # branch to the workflow sha because it is possible that the branch was updated | ||
| # while the workflow was running, which prevents accidentally releasing un-evaluated | ||
| # changes. | ||
| - name: Setup | Checkout Repository on Release Branch | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 0 | ||
| ref: ${{ github.ref_name }} | ||
|
|
||
| - name: Setup | Force release branch to be at workflow sha | ||
| run: | | ||
| git reset --hard ${{ github.sha }} | ||
|
|
||
| - name: Setup | Install uv | ||
| uses: astral-sh/setup-uv@v5 | ||
| with: | ||
| version: "latest" | ||
|
|
||
| - name: Setup | Install Python | ||
| run: uv python install ${{ matrix.python-version }} | ||
|
|
||
|
seansica marked this conversation as resolved.
|
||
| - name: Setup | Install dependencies | ||
| run: uv sync --all-extras | ||
|
|
||
| - name: Semantic Release | ||
| id: release | ||
| uses: python-semantic-release/python-semantic-release@v10.5.3 | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| # NOTE: git_committer_name and git_committer_email are optional | ||
| # We omit them because, if set, they must be associated with the provided token | ||
| # and we don't really care to have a specific committer for automated releases. | ||
|
|
||
| - name: Upload to GitHub Release Assets | ||
| uses: python-semantic-release/publish-action@v10.5.3 | ||
| if: steps.release.outputs.released == 'true' | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| tag: ${{ steps.release.outputs.tag }} | ||
|
|
||
| - name: Upload distribution artifacts | ||
| uses: actions/upload-artifact@v6 | ||
| if: steps.release.outputs.released == 'true' | ||
| with: | ||
| name: distribution-artifacts | ||
| path: dist | ||
| if-no-files-found: error | ||
|
|
||
| outputs: | ||
| released: ${{ steps.release.outputs.released || 'false' }} | ||
|
|
||
| publish: | ||
| # 1. Separate out the deploy step from the publish step to run each step at | ||
| # the least amount of token privilege | ||
| # 2. Also, deployments can fail, and its better to have a separate job if you need to retry | ||
| # and it won't require reversing the release. | ||
| needs: release | ||
| if: needs.release.outputs.released == 'true' | ||
| runs-on: ubuntu-latest | ||
| environment: release | ||
|
|
||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
|
|
||
| steps: | ||
| - name: Download build artifacts | ||
| uses: actions/download-artifact@v4 | ||
|
jondricek marked this conversation as resolved.
Outdated
|
||
| id: artifact-download | ||
| with: | ||
| name: distribution-artifacts | ||
| path: dist | ||
|
|
||
| - name: Publish to PyPI | ||
| uses: pypa/gh-action-pypi-publish@release/v1 | ||
| with: | ||
| packages-dir: dist | ||
| print-hash: true | ||
| verbose: true | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| repos: | ||
| - repo: https://github.com/astral-sh/ruff-pre-commit | ||
| rev: v0.14.10 | ||
| hooks: | ||
| # Run the linter (disabled for now) | ||
| # - id: ruff-check | ||
| # args: [--fix] | ||
| # Run the formatter | ||
| - id: ruff-format | ||
|
|
||
| - repo: https://github.com/commitizen-tools/commitizen | ||
| rev: v4.10.1 | ||
| hooks: | ||
| - id: commitizen | ||
| stages: [commit-msg] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # Default recipe to list all available commands | ||
| default: | ||
| @just --list | ||
|
|
||
| # Install development dependencies | ||
| install: | ||
| uv sync --all-extras | ||
|
|
||
|
seansica marked this conversation as resolved.
|
||
| # Upgrade all uv dependencies | ||
| upgrade: | ||
| uv sync --all-extras --upgrade | ||
|
|
||
| # Install pre-commit hooks | ||
| setup-hooks: | ||
| uv run pre-commit install | ||
| uv run pre-commit install --hook-type commit-msg | ||
|
|
||
| # Run pre-commit hooks on all files | ||
| lint: | ||
| uv run pre-commit run --all-files | ||
|
|
||
| # Run ruff linter | ||
| ruff-check: | ||
| uv run ruff check | ||
|
|
||
| # Run ruff formatter check | ||
| ruff-format-check: | ||
| uv run ruff format --check | ||
|
|
||
| # Run ruff formatter (fix) | ||
| ruff-format: | ||
| uv run ruff format | ||
|
|
||
| # Run tests | ||
| test: | ||
| uv run pytest | ||
|
|
||
| # Run tests with coverage | ||
| test-cov: | ||
| uv run pytest --cov=mitreattack | ||
|
|
||
| # Check commit messages in range (default: last commit) | ||
| check-commits rev-range="HEAD~1..HEAD": | ||
| uv run cz check --rev-range {{ rev-range }} | ||
|
|
||
| # Dry run semantic release (no changes) | ||
| release-dry-run: | ||
| uv run semantic-release -v --noop version | ||
|
|
||
| # Build the package | ||
| build: | ||
| uv build | ||
|
|
||
| # Clean build artifacts | ||
| clean: | ||
| rm -rf dist/ build/ *.egg-info/ | ||
Uh oh!
There was an error while loading. Please reload this page.