Enforce dev → releasepreview → 24h soak → release channel order - #1536
Enforce dev → releasepreview → 24h soak → release channel order#1536IanButterworth wants to merge 2 commits into
Conversation
|
This is great! A few thoughts:
|
| # For a hands-free flow, configure the `release-gate` environment with a | ||
| # wait timer of 1440 minutes: the job is then triggered when the |
There was a problem hiding this comment.
I was not aware what a "wait timer" is, but found it explained in https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments
Thing is, that means that the value 24 hours = 1440 minutes is now encoded in two places, this YAML file and that environment -- that may be unavoidable, and I don't object, but for the sake of future maintainers, who might, like me, not be familiar with this feature, how about including some more specific instructions. Something like this (I am sure someone else can word it better):
| # For a hands-free flow, configure the `release-gate` environment with a | |
| # wait timer of 1440 minutes: the job is then triggered when the | |
| # For a hands-free flow, a repository admin should configure a GitHub | |
| # environment `release-gate` under <https://github.com/JuliaLang/juliaup/settings/environments>, | |
| # with a wait timer of 1440 minutes = 24 hours. | |
| # This job is then triggered when the |
| published=$(date -u -d "$last_modified" +%s) | ||
| now=$(date -u +%s) | ||
| age=$(( now - published )) | ||
| required=$(( 24 * 60 * 60 )) |
There was a problem hiding this comment.
I am very slightly worried that someone will want to change this in the future (e.g. "one week" was already mentioned), and then out of the at least 10 places that hardcode 24 hours (9 places in this file, plus the release-gate GitHub environment) we will forget to update at least one.
How about adding a variable, say MINIMAL_REQUIRED_HOURS=24 or so, and then using that everywhere? Then we'd be down to 2 places. (Technically I guess the variable could be set in the environment config; but I am not sure that's better)
Anyway, this is overall of course a very minor concern. Feel free to ignore.
fingolfin
left a comment
There was a problem hiding this comment.
Seems like a good idea to me. Someone with the appropriate access rights must set up and then maintain the environment, obviously.
Previously all three channel deployments ran in parallel once packaging finished, and the promotion order was enforced only by humans approving the GitHub environments in the right sequence. - The releasepreview deploy jobs now depend on both dev channel deploys, and all release channel jobs depend on a new `release-gate` job that runs after the releasepreview deploys. - `release-gate` verifies against the live releasepreview channel (the RELEASEPREVIEWCHANNELVERSION file juliaup clients poll) that this version is actually published there and that it has been live for at least 24 hours. Because it reads public state, the check holds across re-runs and cannot be bypassed by early environment approval. Configuring the `release-gate` environment with a 1440-minute wait timer makes the soak hands-free; without it the gate fails fast and is re-run after the soak time has elapsed. - The gate can be overridden in an emergency by setting the repository variable RELEASE_GATE_OVERRIDE to the exact version being released and re-running the job; the gate then passes with a prominent warning. Scoping the override to a single version means it cannot be left enabled by accident. - Add the end-to-end self-update tests (command_selfupdate_test, as run in test.yml) as a `test-selfupdate` job gating packaging and the GitHub release alongside `test-juliaup`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Address review feedback: the 24h soak duration was hardcoded in ~9 places. Introduce a single workflow-level RELEASEPREVIEW_SOAK_HOURS variable used by the release-gate script and referenced from comments, so changing the soak period means editing one value here plus the wait timer on the release-gate GitHub environment. Also spell out in the job comment that a repository admin must create that environment under the repo settings and set its wait timer to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7ddbf08 to
cf58867
Compare
|
Feedback addressed. I can't set up the required environment, so I'll hold off merging this for now so we can do a release while @davidanthoff is on vacation. Claude: Manual setup instructionsNothing is needed before merge itself — the setup is all GitHub environment configuration, and it just needs to be in place before the next tagged release. One-time setup (repo admin, before the next
|
Claude:
Previously all three channel deployments (dev / releasepreview / release) ran in parallel once packaging finished — the promotion order was enforced only by humans approving the GitHub environments in the right sequence. This PR makes the order dev → releasepreview → (≥24h soak) → release structural, and adds the end-to-end self-update tests to the test gate at the start of the release process.
Pipeline overview
flowchart TD tag(["push tag v*"]) --> build["build-juliaup<br/>(all targets)"] tag --> test["test-juliaup"] tag --> testsu["<b>test-selfupdate</b><br/>(new: end-to-end<br/>self-update tests)"] subgraph pkg ["packaging — env <b>package</b> (approval)"] direction LR punix["package-unix"] pwin["package-windows<br/>-msix / -msi"] pport["portable<br/>archives"] end build --> pkg test --> pkg testsu --> pkg ghrel["create-github-release<br/>(as prerelease)"] test --> ghrel testsu --> ghrel ghrel --> ghbin["deploy-github-release-binaries<br/>(prerelease assets)"] pport --> ghbin subgraph dev ["stage 1: dev channel — env <b>dev-channel</b> (approval)"] direction LR devws["winstore flight"] devs3["S3<br/>DEVCHANNELVERSION"] end ghrel --> dev punix --> dev pwin --> dev subgraph rp ["stage 2: releasepreview channel — env <b>release-preview-channel</b> (approval)"] direction LR rpws["winstore flight"] rps3["S3<br/>RELEASEPREVIEWCHANNELVERSION"] end dev --> rp gate{{"<b>release-gate</b> — env <b>release-gate</b><br/>wait timer: 24h (recommended setup)<br/>checks live channel: serves this version AND live ≥ 24h<br/>override: RELEASE_GATE_OVERRIDE variable (warns)"}} rp --> gate subgraph rel ["stage 3: release channel — env <b>release-channel</b> (approval)"] direction LR relws["winstore"] rels3["S3 + MSI"] relbrew["Homebrew"] relaur["AUR"] relgh["GitHub release<br/>(prerelease → release)"] relcrates["crates.io"] end gate --> relOrdering via
needsdeploy-releasepreview-channel-{winstore,s3}now depend on both dev channel deploys.deploy-release-channel-*jobs now depend on a newrelease-gatejob, which depends on both releasepreview deploys.The 24h soak gate
release-gateverifies against the live releasepreview channel — theRELEASEPREVIEWCHANNELVERSIONfile juliaup clients actually poll — that:Last-Modifiedis at least 24 hours old.Because the check reads public state rather than workflow-internal timestamps, it cannot be bypassed by approving the release environment early, and it survives workflow re-runs.
Recommended one-time setup: create the
release-gateenvironment (it is auto-created on first run) and give it a wait timer of 1440 minutes. The gate is then triggered when releasepreview finishes, sleeps 24h on GitHub's side, and passes on its own — fully hands-free. Without the wait timer the gate fails fast when run too early and must be re-run ("Re-run failed jobs") once the soak has elapsed; either way the 24h minimum is enforced.Emergency override: set the repository variable
RELEASE_GATE_OVERRIDEto the exact version being released and re-run the gate. It passes immediately with a prominent warning annotation and a note in the job summary. Scoping the override to one version means it cannot be left enabled by accident (a stale value is ignored with a notice).Self-update tests in the release test gate
A
test-selfupdatejob (identical to the one intest.yml, runningcommand_selfupdate_testwith theselfupdatefeature on Linux + macOS) now gates all packaging jobs andcreate-github-releasealongsidetest-juliaup, so a release cannot proceed if the end-to-end self-update path is broken.🤖 Generated with Claude Code