Repository navigation
Conversation
Pin every action to a commit SHA with the tag in a trailing comment, add `persist-credentials: false` to each checkout, and declare `permissions: contents: read` at the top of CI. CI gains a concurrency group that cancels only pull request runs; a run on main or a scheduled run covers a commit or a point in time nothing else re-covers. The `test` job now processes coverage and uploads it to Codecov with `fail_ci_if_error: false`. `test-full` runs on a pull request carrying the `full-matrix` label, so a `[compat]` bump can get macOS/arm64 and multi-version coverage before it lands, and it no longer instruments coverage, which the `test` job already does. The benchmark job is restricted to pull requests from a branch of this repository. A fork pull request receives a read-only GITHUB_TOKEN whatever the `permissions` block requests, so the comparison comment gets a 403 and the check fails for a reason unrelated to the change. Its AirspeedVelocity pin moves to v0.6.5. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both docs workflows now use `julia-actions/cache`, so the PowerIO native
library artifact and the PGLib_opf archive are restored instead of
re-downloaded on every build. `[sources] PowerDiff = {path = ".."}` in
docs/Project.toml already resolves PowerDiff to the checkout, so the
`Pkg.develop` call is gone from both and `Pkg.instantiate()` is the whole
install.
Documentation.yml builds through `julia-actions/julia-docdeploy` with
`install-package: false`, narrows its tag trigger to `v*` (Documenter maps
only `vX.Y.Z` to a versioned docs directory), and gains a docs concurrency
group. Its permission set drops `actions: write`: Documenter needs
`contents: write` to push gh-pages, `statuses: write` to attach the preview
link and `pull-requests: read` to resolve the preview path, and none of it
touches the Actions API.
DeployDocsSite.yml declares `permissions: contents: read` (it publishes to
another repository through a PAT), triggers on CHANGELOG.md as well, and
serializes on a concurrency group. The website repository is now obtained
with a second `actions/checkout`, which supplies WEBSITE_DEPLOY_TOKEN as an
`http.extraheader` and strips it in post-job cleanup, rather than splicing
it into a clone URL where it lands on a command line and persists in
_website/.git/config. That checkout runs after the docs build because it
cleans only its own path, while the root checkout cleans the workspace.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Register.yml takes a full 40-character `expected_sha` and a `dry_run` flag, checks out that exact commit, and posts one JuliaRegistrator trigger comment on it. It writes no tracked file, pushes no branch and creates no tag; the version bump in Project.toml and the CHANGELOG promotion land through a reviewed pull request. That ordering matters because a commit pushed by a workflow with GITHUB_TOKEN starts no further workflow, so a bump written from CI is the one commit on main that CI never runs against. The gate, in order: `expected_sha` is well-formed and is the current tip of main; Project.toml carries an X.Y.Z version; the changelog has a section for that version, skipping an empty `## [Unreleased]` and rejecting a non-empty one, whose body holds at least one bullet and mentions "breaking" or "changelog" as General's `guideline_breaking_explanation` check requires; the version is absent from General's Versions.toml and higher than every version in it; the tag does not exist; and the full test suite passes on the tree being registered. The release notes travel by file path through `$GITHUB_OUTPUT` and are encoded with `jq -Rs`, so changelog text never reaches a shell expansion or a heredoc delimiter. Posting is skipped when the commit already carries a trigger comment, making a re-run safe. TagBot keeps its trigger, actor gate and token/ssh fallbacks, and gains a serializing concurrency group and a `changelog_ignore` list for housekeeping and bot labels. Its `changelog` template stays at TagBot's default, which already renders the heading, the diff link, the notes carried by the Registrator trigger, and the merged pull requests and closed issues. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
docs/make.jl renders CHANGELOG.md into docs/src/changelog.md with Changelog.jl before makedocs runs, so issue, pull request and version references become links, and adds the page after the API reference. CHANGELOG.md at the repository root stays the single source; the rendered page is generated on every build and is gitignored. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
RELEASING.md gives the seven steps of a release: the release pull request that bumps Project.toml and promotes the changelog section, the merge and CI-green wait, reading the tip of main, dispatching Register with that SHA, AutoMerge, TagBot, and the checks that confirm the release landed. Every constraint it states is one the Register workflow enforces. CONTRIBUTING.md gives the test, docs and benchmark commands, records that the benchmark check is skipped on fork pull requests by design, and describes the `full-matrix` and `changelog skip` labels that the pull request template refers to. The pull request template prompts for a description, a changelog bullet or the `changelog skip` label, and the three checks a reviewer would otherwise ask about. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Everything on main since v0.1.0 goes out in this release: v0.1.0 was registered against PowerIO 0.6, so the 0.7 through 0.11 work, the public KKT layout, the energized-branch angle gates and the pull request benchmarks have all been unreleased until now. The changelog moves to Keep a Changelog form, which is what Changelog.jl renders into the documentation and what the registration workflow validates. Compat gains the two stdlibs that had none, and the install instructions use the registered package, which has been in General since 0.0.1. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`on: pull_request` defaults to `opened, synchronize, reopened`, so applying a label starts no run and the matrix job the label gates stays skipped until the next push. Listening for `labeled` is what makes the gate reachable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Benchmark Results (Julia v1)Time benchmarks
Memory benchmarks
|
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release automation brought to current Julia practice, plus the v0.2.0 version bump
and changelog. Stacked on #76 — the diff shown here is only the release work.
Registration stops mutating
mainregister.ymlbumped the version, committed it, pushed tomain, and posted theJuliaRegistrator trigger. Reading it turned up six defects, each confirmed:
GITHUB_TOKENstarts no workflow, so the
Set version to X.Y.Zcommit it created was the onecommit on
mainno CI ever saw. There was noPkg.test()anywhere in the file.git commit -am … || echoswallowed any failure;
git pushthen no-opped,git rev-parse HEADreturned thepre-bump tip, and the workflow registered the previous version.
mainfrom CI, with noconcurrencygroup.awkrange printed the## X.Y.Zheading into the release-notes body.$GITHUB_OUTPUTused a fixed heredoc delimiter a changelog line could terminate.Register.ymlreplaces it and writes nothing. The version bump and the changelogsection land through an ordinary reviewed pull request, so CI runs on the exact tree
that gets registered. The workflow then takes that commit's SHA and refuses unless it
is the current tip of
main; validates and extracts the top changelog section;requires the notes to mention "breaking" or "changelog", because General runs
guideline_breaking_explanationand every pre-1.0 minor bump is breaking; checks theversion against General's
Versions.tomlfor duplicates and ordering; checks the tagdoes not exist; re-runs
Pkg.test()on that tree; refuses to post twice for the samecommit; and offers a dry run. The notes travel as a file path and the comment body is
built with
jq -Rs, so the changelog text never passes through a shell expansion.Automatic changelog, in two layers
section carried by the Registrator trigger, a diff link, and the pull requests
merged since the last release. Only
changelog_ignoreis added, filteringhousekeeping by label. Overriding the template would mean owning it forever for no
gain.
CHANGELOG.md: now Keep a Changelog, rendered into the docs byChangelog.jl(registered, used by Documenter.jl itself), which linkifies
[#123]and generatesdocs/src/changelog.mdat build time. That page is generated, never tracked.CI hardening
Explicit
permissions:on every workflow — there were none outsideBenchmark.yml,so everything inherited the repository default. Concurrency groups that supersede
in-flight pull request runs but never cancel a run on
mainor a scheduled one.Every third-party action pinned to a commit SHA with a
# vX.Y.Zcomment, includingjulia-actions/*, which execute arbitrary Julia in the job; Dependabot alreadyupdates SHA pins and rewrites the version comment. Coverage through Codecov with
fail_ci_if_error: false.Documentation.ymlgains caching — it had none, so every docs build re-downloadedthe PowerIO native artifact — and drops the
Pkg.developmade redundant by[sources]. Its tag trigger narrows tov*.actions: writeis dropped; Documenterdoes not need the Actions API, and
julia-actions/cacheskips old-cache pruning onthe default branch and tolerates a 403 elsewhere.
DeployDocsSite.ymlstops splicing its PAT into agit cloneURL, where the secretlanded on the command line and persisted in
_website/.git/configfor the rest of thejob. A second
actions/checkoutwrites the credential as anhttp.extraheaderandstrips it in post-job cleanup.
Benchmark.ymlskips pull requests from forks. This is what put the red X on #77through no fault of the contributor: a fork gets a read-only
GITHUB_TOKENregardless of the workflow's
pull-requests: write, so the step that posts thebenchmark comment 403s. Not
pull_request_target, which would run a fork's scriptwith a write-scoped token.
test-fullalso runs on a pull request labelledfull-matrix, so a compat bump getsmatrix coverage before it lands rather than after.
v0.2.0
version = "0.2.0", and the changelog promoted to## [0.2.0] - 2026-09-05.Worth stating plainly: v0.1.0 was registered against PowerIO 0.6, and
mainis 13commits ahead of it. This release is not just the PowerIO 0.11 port and the
restoration example — it is everything unreleased since July, including the public
KKT layout (#72), the energized-branch angle gates (#71) and the pull request
benchmarks (#70).
Compat gains
LinearAlgebraandSparseArrays, which had none. Not required today,since RegistryCI's stdlib check is off, but the upstream comment says they intend to
turn it on. Install instructions use
Pkg.add("PowerDiff"); the package has been inGeneral since 0.0.1.
New files
RELEASING.md(seven steps, one screen),CONTRIBUTING.md, and a short pull requesttemplate whose one load-bearing item is the changelog checkbox, since
Register.ymlnow hard-fails on a missing section.
Verification
actionlint1.7.7 with shellcheck is clean.Register.yml's changelog step was extracted from the YAML and run against 12fixtures, including a hostile body containing
$(touch /tmp/pwned), quotes, and aliteral
RELEASE_NOTES_EOF. No injection fired and the heading is excluded from thenotes. It was then run against this pull request's actual
CHANGELOG.md: accepted,heading excluded, "breaking" matched.
ChangelogUUID verified against General.To release v0.2.0 once this merges
RELEASING.mdhas it, and steps 1 and 2 are this stack:mainis then the release commit.git fetch origin && git rev-parse origin/maindry_runfirst to seethe trigger comment without posting it.
v0.2.0and publishes the release within the hour.One thing to do by hand, before the release: run TagBot once via
workflow_dispatchto backfill the missing
v0.0.1GitHub release, and create thechangelog skip,full-matrixandreleaselabels.🤖 Generated with Claude Code