Skip to content

Automate release pipeline with towncrier-fragments version scheme #47

Automate release pipeline with towncrier-fragments version scheme

Automate release pipeline with towncrier-fragments version scheme #47

Workflow file for this run

name: test
on:
push:
branches:
- main
- test-me-*
pull_request:
branches:
- main
# Set permissions at the job level.
permissions: {}
jobs:
check-package:
name: Build & inspect our package.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Detect release branch version
id: release
if: startsWith(github.head_ref || '', 'release-')
run: |
VERSION="${GITHUB_HEAD_REF#release-}"
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PLUGGY=$VERSION" >> "$GITHUB_ENV"
fi
- uses: hynek/build-and-inspect-python-package@fe0a0fb1925ca263d076ca4f2c13e93a6e92a33e # v2.17.0
test:
needs: [check-package]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
name: [
"windows-py310",
"windows-py314",
"windows-pypy3",
"ubuntu-py310-pytestmain",
"ubuntu-py310",
"ubuntu-py311",
"ubuntu-py312",
"ubuntu-py313",
"ubuntu-py314",
"ubuntu-pypy3",
"ubuntu-benchmark",
]
include:
- name: "windows-py310"
python: "3.10"
os: windows-latest
tox_env: "py310"
- name: "windows-py313"
python: "3.13"
os: windows-latest
tox_env: "py313"
- name: "windows-py314"
python: "3.14"
os: windows-latest
tox_env: "py314"
- name: "windows-pypy3"
python: "pypy3.10"
os: windows-latest
tox_env: "pypy3"
- name: "ubuntu-py310-pytestmain"
python: "3.10"
os: ubuntu-latest
tox_env: "py310-pytestmain"
use_coverage: true
- name: "ubuntu-py310"
python: "3.10"
os: ubuntu-latest
tox_env: "py310"
use_coverage: true
- name: "ubuntu-py311"
python: "3.11"
os: ubuntu-latest
tox_env: "py311"
use_coverage: true
- name: "ubuntu-py312"
python: "3.12"
os: ubuntu-latest
tox_env: "py312"
use_coverage: true
- name: "ubuntu-py313"
python: "3.13"
os: ubuntu-latest
tox_env: "py313"
use_coverage: true
- name: "ubuntu-py314"
python: "3.14"
os: ubuntu-latest
tox_env: "py314"
use_coverage: true
- name: "ubuntu-pypy3"
python: "pypy3.10"
os: ubuntu-latest
tox_env: "pypy3"
use_coverage: true
- name: "ubuntu-benchmark"
python: "3.10"
os: ubuntu-latest
tox_env: "benchmark"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Download built packages from the check-package job.
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: Packages
path: dist
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python }}
allow-prereleases: true
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools
python -m pip install tox coverage
- name: Test without coverage
if: "! matrix.use_coverage"
shell: bash
run: "tox run --installpkg dist/*.whl"
env:
TOX_ENV: ${{ matrix.tox_env }}
- name: Test with coverage
if: "matrix.use_coverage"
shell: bash
run: "tox run --installpkg dist/*.whl"
env:
TOX_ENV: ${{ matrix.tox_env }}-coverage
- name: Upload coverage
if: matrix.use_coverage && github.repository == 'pytest-dev/pluggy'
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
continue-on-error: true
with:
fail_ci_if_error: true
files: ./coverage.xml
verbose: true
release-artifacts:
name: Update draft GitHub release
needs: [check-package, test]
if: >-
github.repository == 'pytest-dev/pluggy'
&& github.event_name == 'pull_request'
&& startsWith(github.head_ref, 'release-')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Determine version from branch
id: version
run: |
VERSION="${GITHUB_HEAD_REF#release-}"
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
echo "::notice::Branch $GITHUB_HEAD_REF is not a release version branch — skipping."
exit 0
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
if: steps.version.outputs.version
with:
persist-credentials: false
- name: Download built packages
if: steps.version.outputs.version
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: Packages
path: dist
- name: Create or update draft release
if: steps.version.outputs.version
uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0
env:
VERSION: ${{ steps.version.outputs.version }}
HEAD_REF: ${{ github.head_ref }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
with:
script: |
const fs = require('fs');
const path = require('path');
const { VERSION, HEAD_REF, HEAD_SHA } = process.env;
const tag = VERSION;
const title = `pluggy ${VERSION}`;
const body = `Release ${VERSION} — built from \`${HEAD_REF}\` at ${HEAD_SHA}.`;
let release;
try {
const { data } = await github.rest.repos.getReleaseByTag({
...context.repo,
tag,
});
release = data;
} catch (e) {
if (e.status !== 404) throw e;
}
if (release && !release.draft) {
core.notice(`Release ${VERSION} is already published — skipping.`);
return;
}
if (release) {
// Update existing draft: replace assets with freshly tested ones.
await github.rest.repos.updateRelease({
...context.repo,
release_id: release.id,
tag_name: tag,
name: title,
body,
draft: true,
target_commitish: HEAD_SHA,
});
for (const asset of release.assets) {
await github.rest.repos.deleteReleaseAsset({
...context.repo,
asset_id: asset.id,
});
}
} else {
const { data } = await github.rest.repos.createRelease({
...context.repo,
tag_name: tag,
name: title,
body,
draft: true,
target_commitish: HEAD_SHA,
});
release = data;
}
// Upload all assets from dist/.
for (const file of fs.readdirSync('dist')) {
const filePath = path.join('dist', file);
await github.rest.repos.uploadReleaseAsset({
...context.repo,
release_id: release.id,
name: file,
data: fs.readFileSync(filePath),
});
core.info(`Uploaded ${file}`);
}