Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 5 additions & 79 deletions .github/workflows/cetlvast.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: "CETLVaSt"
run-name: CETLVaSt / ${{ inputs.docs_ref || github.ref_name }}
run-name: CETLVaSt / ${{ github.ref_name }}

permissions:
contents: read

concurrency:
group: cetlvast-${{ github.ref }}-${{ inputs.docs_ref }}
group: cetlvast-${{ github.ref }}
cancel-in-progress: false

on:
Expand All @@ -14,14 +14,7 @@ on:
branches:
- main
- "issue/*"
release:
types: [published]
workflow_dispatch:
inputs:
docs_ref:
description: "Release tag to verify in full and deploy from main (stable releases only)."
required: false
default: ""

jobs:
version:
Expand All @@ -30,22 +23,14 @@ jobs:
commit: ${{ steps.version.outputs.commit }}
tag: ${{ steps.version.outputs.tag }}
version: ${{ steps.version.outputs.version }}
prerelease: ${{ steps.version.outputs.prerelease }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ inputs.docs_ref || github.event.release.tag_name || github.sha }}
ref: ${{ github.sha }}
fetch-depth: 0
- name: Validate library and release versions
id: version
env:
DOCS_REF: ${{ inputs.docs_ref }}
run: |
if [ -n "$DOCS_REF" ]; then
python3 scripts/release_tools.py validate --tag "$DOCS_REF"
else
python3 scripts/release_tools.py validate
fi
run: python3 scripts/release_tools.py validate

release-tests:
runs-on: ubuntu-latest
Expand All @@ -63,7 +48,6 @@ jobs:
cache-warmup:
if: >
startsWith(github.ref, 'refs/tags/v') ||
github.event_name == 'release' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.head_commit.message, '#verification') ||
contains(github.event.head_commit.message, '#docs') ||
Expand Down Expand Up @@ -91,7 +75,6 @@ jobs:
verification-amd64:
if: >
startsWith(github.ref, 'refs/tags/v') ||
github.event_name == 'release' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.head_commit.message, '#verification') ||
contains(github.ref, '/main') ||
Expand Down Expand Up @@ -135,7 +118,6 @@ jobs:
verification-arm64:
if: >
startsWith(github.ref, 'refs/tags/v') ||
github.event_name == 'release' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.head_commit.message, '#verification') ||
contains(github.ref, '/main') ||
Expand Down Expand Up @@ -180,7 +162,6 @@ jobs:
verification-legacy-arm64:
if: >
startsWith(github.ref, 'refs/tags/v') ||
github.event_name == 'release' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.head_commit.message, '#verification') ||
contains(github.ref, '/main') ||
Expand Down Expand Up @@ -226,7 +207,6 @@ jobs:
docs:
if: >
startsWith(github.ref, 'refs/tags/v') ||
github.event_name == 'release' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.head_commit.message, '#verification') ||
contains(github.event.head_commit.message, '#docs') ||
Expand Down Expand Up @@ -262,15 +242,6 @@ jobs:
run: >-
python3 scripts/release_tools.py verify-docs --version "$CETL_RELEASE_VERSION"
--path cetlvast/build/suites/docs/html/index.html
- name: Setup Pages
if: ${{ github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}
uses: actions/configure-pages@v6
- name: Upload docs
if: ${{ github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}
uses: actions/upload-pages-artifact@v5
with:
path: "cetlvast/build/suites/docs/html/"

- name: Save built release documentation
uses: actions/upload-artifact@v7
with:
Expand All @@ -284,7 +255,6 @@ jobs:
if: >-
always() && (
startsWith(github.ref, 'refs/tags/v') ||
github.event_name == 'release' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.head_commit.message, '#verification') ||
contains(github.ref, '/main') ||
Expand Down Expand Up @@ -320,16 +290,10 @@ jobs:
path: release-docs
- name: Package the verified source, headers, and documentation
env:
RELEASE_TAG: ${{ needs.version.outputs.tag }}
RELEASE_COMMIT: ${{ needs.version.outputs.commit }}
LIBRARY_VERSION: ${{ needs.version.outputs.version }}
run: |
# PR/branch runs rehearse packaging using a local tag; it is never pushed.
if [ -z "$RELEASE_TAG" ]; then
RELEASE_TAG="v$LIBRARY_VERSION-rc.$GITHUB_RUN_ID"
git tag "$RELEASE_TAG" "$RELEASE_COMMIT"
fi
python3 scripts/release_tools.py package --tag "$RELEASE_TAG" --commit "$RELEASE_COMMIT" \
python3 scripts/release_tools.py package --tag "v$LIBRARY_VERSION" --commit "$RELEASE_COMMIT" \
--docs release-docs --output release-bundle
python3 - <<'PYTHON'
import json
Expand Down Expand Up @@ -363,41 +327,3 @@ jobs:
if-no-files-found: error
overwrite: true
retention-days: 30

deploy-docs:
if: ${{ github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' && needs.version.outputs.tag != '' && needs.version.outputs.prerelease == 'false' }}
needs: [version, release-ready, release-assets]
concurrency:
group: cetl-stable-pages
cancel-in-progress: false
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
contents: read
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source

# Deploy to the github-pages environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

# Specify runner + deployment step
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ needs.version.outputs.commit }}
- name: Prevent unpublished releases or older retries from replacing stable docs
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ needs.version.outputs.tag }}
PYTHONPATH: scripts
run: |
python3 - <<'PYTHON'
import os
from release import GitHub, require_latest_stable
require_latest_stable(GitHub(os.environ['GITHUB_REPOSITORY']), os.environ['RELEASE_TAG'])
PYTHON
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
107 changes: 107 additions & 0 deletions .github/workflows/release-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: Release documentation
run-name: CETL docs / ${{ inputs.tag }}

on:
workflow_dispatch:
inputs:
tag:
description: Published release tag
required: true
type: string
release_id:
description: Release ID supplied by the release script
required: true
type: number

permissions:
contents: read
actions: read
pages: write
id-token: write

concurrency:
group: cetl-stable-pages
cancel-in-progress: false

jobs:
deploy-docs:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.sha }}
fetch-depth: 0
- uses: actions/setup-python@v7
with:
python-version: '3.14'
- name: Validate release identity
id: version
env:
RELEASE_TAG: ${{ inputs.tag }}
PYTHONPATH: scripts
run: |
python3 - <<'PYTHON'
import os
from pathlib import Path
from release_tools import Git, parse_version

tag = os.environ['RELEASE_TAG']
if not tag.startswith('v'):
raise SystemExit('Expected a vX.Y.Z tag')
parse_version(tag[1:])
git = Git(Path.cwd())
commit = git.commit('refs/tags/' + tag)
git.run('merge-base', '--is-ancestor', commit, 'HEAD')
metadata = {**git.validate(commit, tag), 'commit': commit}
with open(os.environ['GITHUB_OUTPUT'], 'a') as output:
for key, value in metadata.items():
output.write(f'{key}={value}\n')
PYTHON
- name: Download and verify published documentation
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ steps.version.outputs.tag }}
RELEASE_COMMIT: ${{ steps.version.outputs.commit }}
RELEASE_ID: ${{ inputs.release_id }}
PYTHONPATH: scripts
run: |
python3 - <<'PYTHON'
import os
from pathlib import Path
from release import GitHub, require_latest_stable, wait_for_release_run
from release_tools import extract_documentation

github = GitHub(os.environ['GITHUB_REPOSITORY'])
tag, commit = os.environ['RELEASE_TAG'], os.environ['RELEASE_COMMIT']
release = github.release_by_id(int(os.environ['RELEASE_ID']))
require_latest_stable(github, tag, release)
wait_for_release_run(github, commit, 300, 15)
bundle = Path('release-bundle')
bundle.mkdir()
github.download_assets(release, bundle)
extract_documentation(bundle, commit, tag, 'site')
PYTHON
- uses: actions/configure-pages@v6
- uses: actions/upload-pages-artifact@v5
with:
path: site/cetl-${{ steps.version.outputs.version }}/html
- name: Confirm release is still latest
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ steps.version.outputs.tag }}
RELEASE_ID: ${{ inputs.release_id }}
PYTHONPATH: scripts
run: |
python3 - <<'PYTHON'
import os
from release import GitHub, require_latest_stable
github = GitHub(os.environ['GITHUB_REPOSITORY'])
release = github.release_by_id(int(os.environ['RELEASE_ID']))
require_latest_stable(github, os.environ['RELEASE_TAG'], release)
PYTHON
- uses: actions/deploy-pages@v5
id: deployment
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ Note that if the job you requested is dependent on other jobs that are not trigg

Version/header validation and release-tool tests run independently of hashtags.
The `#verification` trigger includes documentation and release archive checks.
Version tags and release dispatches always run full verification. A release
documentation dispatch also verifies the complete release; it is not a docs-only shortcut.
Version tags and verification dispatches run full verification. Documentation
deployment verifies the published bundle and its successful main CI run, then
deploys the packaged documentation.
See [Releasing CETL](RELEASING.md) for the maintainer Python CLI and recovery instructions.
The CMake `release` target is a legacy build/test alias and does not publish a release.

Expand Down
39 changes: 10 additions & 29 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,17 @@
# Releasing CETL

Merge the reviewed changes and version bump into `main`. Choose patch versions for
compatible fixes, minor versions for compatible additions, and major versions for
incompatible changes. Documentation/test-only changes do not require a version bump.
Merge the reviewed changes and version bump in `include/cetl/cetl.hpp` into `main`.
Choose patch versions for compatible fixes, minor versions for compatible additions,
and major versions for incompatible changes.

```sh
python3 scripts/release.py --dry-run
python3 scripts/release.py
```

Run the printed **Release this checked commit** command to publish exactly the
version and commit that passed preflight. The script fetches remote `main`, reads
the header version, checks the tools/access/workflow/Pages setup, waits for full CI,
verifies the archives, publishes the release, and verifies the deployed documentation.
Failures report the corrective action. No manual test, checksum, or site-version
check is required.
The script fetches `main`, reads the header version, verifies CI and the release
bundle, then creates the tag, publishes the release, and deploys documentation.
Failed verification leaves the version available for a corrected commit.

For a prerelease, supply its version explicitly:

```sh
python3 scripts/release.py --version 2.0.0-rc.1 --dry-run
```

Use `--ref COMMIT` to select a particular merged commit and `--notes-file PATH` for
reviewed release notes; otherwise GitHub generates the notes. See `--help` for
forks, alternate remotes, and wait limits.

## Recovery

Run the printed **Resume command** after fixing the reported problem. It retains
matching tags/assets, finishes missing uploads, and retries documentation deployment.
Published releases are verified from their actual assets, so expired CI artifacts
do not require manual recovery. Conflicting tags or asset contents are refused.

For a transient CI failure, run the full-run retry command printed in the error,
then resume. A source fix needs a new reviewed commit and a new version/tag.
If interrupted, run the command again. Matching tags, drafts, and uploaded assets
are reused. The script also prints a retry command pinned to the selected commit.
Conflicting tags or asset contents are refused.
Loading
Loading