Release #74
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Release | |
on: | |
push: | |
tags: ["v*"] | |
workflow_dispatch: | |
inputs: | |
tag: | |
type: string | |
description: The tag of the release, leave empty for latest. | |
required: false | |
env: | |
GH_TOKEN: ${{ github.token }} | |
PIP_DISABLE_PIP_VERSION_CHECK: 1 | |
jobs: | |
prep: | |
name: Prepare | |
runs-on: windows-latest | |
outputs: | |
tag: ${{ steps.determine_tag.outputs.tag }} | |
message: ${{ steps.determine_tag.outputs.message }} | |
steps: | |
- name: Determine Release Tag | |
id: determine_tag | |
uses: actions/github-script@v7 | |
with: | |
# noinspection TypeScriptUnresolvedReference | |
script: | | |
const specified_tag = context.payload.inputs && context.payload.inputs.tag | |
let tag = undefined | |
let commit = undefined | |
for await (const tags of github.paginate.iterator( | |
github.rest.repos.listTags, | |
{ | |
owner: context.repo.owner, | |
repo: context.repo.repo | |
} | |
)) { | |
for (const tag_data of tags.data) { | |
core.info(`Checking tag ${tag_data.name}`) | |
const commit_data = (await github.rest.repos.getCommit({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
ref: tag_data.commit.sha | |
})).data.commit | |
if (specified_tag) { | |
if (tag_data.name == context.payload.inputs.tag) { | |
tag = tag_data | |
commit = commit_data | |
} | |
} else { | |
if (tag == undefined || Date.parse(commit_data.committer.date) > Date.parse(commit.committer.date)) { | |
tag = tag_data | |
commit = commit_data | |
} | |
} | |
} | |
} | |
if (tag == undefined) { | |
core.setFailed("Failed to determine a tag.") | |
return | |
} | |
core.notice(`Using tag: ${tag.name}`) | |
core.notice(`Message: ${commit.message}`) | |
core.setOutput("tag", tag.name) | |
core.setOutput("message", commit.message) | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ steps.determine_tag.outputs.tag }} | |
- name: Validate Tag | |
uses: actions/github-script@v7 | |
env: | |
TAG_NAME: ${{ steps.determine_tag.outputs.tag }} | |
with: | |
# noinspection TypeScriptUnresolvedReference | |
script: | | |
const tag_validator = /v\d(?:\.\d)+/ | |
const version_pattern = /version\s*=\s*"(?<version>[^"]+])"/ | |
const tag = process.env.TAG_NAME | |
core.info(`Tag: ${tag}`) | |
if (!tag.match(tag_validator)) { | |
core.setFailed(`Invalid version tag: must match "${tag_validator}".`) | |
return | |
} | |
const fs = require("node:fs") | |
const readline = require("node:readline") | |
for await (const line of readline.createInterface({ | |
input: fs.createReadStream("pyproject.toml"), | |
crlfDelay: Infinity | |
})) { | |
const match = line.match(version_pattern) | |
if (match) { | |
core.info(`Version from pyproject.toml: ${match.groups.version}`) | |
if (tag.substring(1) != match.groups.version) | |
core.setFailed("Tag doesn't match the version defined in pyproject.toml") | |
return | |
} | |
} | |
core.info("Tag matches with module version from pyproject.toml") | |
codegen: | |
name: Codegen | |
needs: prep | |
uses: ./.github/workflows/codegen.yml | |
with: | |
ref: ${{ needs.prep.outputs.tag }} | |
source_dists: | |
name: Source Dists | |
runs-on: ubuntu-latest | |
needs: [codegen, prep] | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ needs.prep.outputs.tag }} | |
- name: Download Codegen Output | |
uses: actions/download-artifact@v4 | |
with: | |
name: codegen_results | |
path: src/spatium | |
- name: Setup Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: 3.12 | |
- name: Install Dependencies | |
run: pip install -r requirements.txt | |
- name: Build | |
run: python setup.py sdist --formats=gztar,zip | |
- name: Upload Artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: dists_src | |
path: dist/ | |
retention-days: 1 | |
- name: Fail-Fast | |
if: failure() | |
uses: andymckay/[email protected] | |
binary_dists: | |
name: Binary Dists | |
runs-on: ${{ matrix.platform }} | |
needs: [codegen, prep] | |
strategy: | |
fail-fast: true | |
matrix: | |
python: ["cp39", "cp310", "cp311", "cp312", "pp39", "pp310"] | |
platform: ["windows-latest", "ubuntu-latest", "macos-latest"] | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ needs.prep.outputs.tag }} | |
- name: Download Codegen Output | |
uses: actions/download-artifact@v4 | |
with: | |
name: codegen_results | |
path: src/spatium | |
- name: CIBuildWheel | |
uses: pypa/[email protected] | |
with: | |
output-dir: dist | |
env: | |
CIBW_BUILD: "${{ matrix.python }}-*" | |
- name: Upload to Artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: dists_bin_${{ matrix.python }}_${{ matrix.platform }} | |
path: dist/ | |
retention-days: 1 | |
- name: Fail-Fast | |
if: failure() | |
uses: andymckay/[email protected] | |
github_release: | |
name: GitHub Release | |
runs-on: ubuntu-latest | |
needs: [source_dists, prep] | |
permissions: | |
contents: write | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Download Artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: dists_src | |
path: dist | |
- name: Remove Old Release | |
uses: actions/github-script@v7 | |
env: | |
TAG_NAME: ${{ needs.prep.outputs.tag }} | |
with: | |
# noinspection TypeScriptUnresolvedReference | |
script: | | |
const tag = process.env.TAG_NAME | |
let release | |
try { | |
release = (await github.rest.repos.getReleaseByTag({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
tag: tag | |
})).data | |
} catch (error) { | |
if (error.status === 404) { | |
core.info(`No release with tag ${tag}.`) | |
return | |
} | |
throw error | |
} | |
await github.rest.repos.deleteRelease({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
release_id: release.id | |
}) | |
core.notice(`Deleted old github release: ${tag}`) | |
- name: Create Release | |
run: gh release create "${{ needs.prep.outputs.tag }}" --verify-tag --title "${{ needs.prep.outputs.tag }}" --notes "${{ needs.prep.outputs.message }}" --draft | |
- name: Upload | |
shell: pwsh | |
run: | | |
foreach ($file in (Get-ChildItem dist/*)) { | |
gh release upload "${{ needs.prep.outputs.tag }}" "$($file.FullName)" | |
} | |
- name: Publish | |
run: gh release edit ${{ needs.prep.outputs.tag }} --draft=false | |
- name: Fail-Fast | |
if: failure() | |
uses: andymckay/[email protected] | |
pypi_upload: | |
name: PyPI Upload | |
runs-on: ubuntu-latest | |
needs: [source_dists, binary_dists] | |
permissions: | |
id-token: write # pypi trusted publishing | |
steps: | |
- run: mkdir dist | |
- name: Download Artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
pattern: "dists*" | |
path: dist | |
merge-multiple: true | |
- name: Delete Redundant Source Dist | |
shell: pwsh | |
# only keep .tar.gz | |
run: rm dist/*.zip | |
# use trusted publishing | |
- name: Upload | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
# with: | |
# repository-url: https://test.pypi.org/legacy/ | |
- name: Fail-Fast | |
if: failure() | |
uses: andymckay/[email protected] |