mirror of
https://github.com/storytold/craft-common-actions.git
synced 2026-11-15 15:02:24 +00:00
release.yml: a dry-run input builds and checks without releasing (#208)
* release.yml: a dry-run input builds and checks without releasing For a nightly run on main that finds release-only breakage before release day. On 11 Nov 2026 gridcraft's riscv64 build, materialcraft's private-repo FreeBSD jobs, wordcraft's Print job and the riscv64 apt mirrors each surfaced only during the release, one fix PR and release run at a time. With dry-run: no job enters the release environment (no signing secrets; the environment admits only the release branch), the macOS job and the draft are skipped, and the Flatpak OCI layouts are not pushed to GHCR or Docker Hub. * tests: the Flatpak OCI push and the release environment also stay out of a dry run
This commit is contained in:
1 parent
15058dc71e
commit
603045e42d
4 files changed
+60
-11
No files matched your search
@@ -84,6 +84,14 @@ on:
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
dry-run:
|
||||
description: >-
|
||||
Build and check without releasing: no signing, no `release` environment, no macOS (its
|
||||
larger runner is paid for), no Flatpak OCI push and no draft. For a nightly run on main
|
||||
that finds release-only breakage (riscv64, Flatpak, FreeBSD, packaging) before release day.
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
|
||||
secrets:
|
||||
APPLE_CERTIFICATE:
|
||||
@@ -214,9 +222,10 @@ jobs:
|
||||
macos:
|
||||
timeout-minutes: 90
|
||||
name: macOS universal
|
||||
if: ${{ !inputs.dry-run }}
|
||||
needs: [version]
|
||||
runs-on: macos-15-xlarge
|
||||
environment: release
|
||||
environment: ${{ !inputs.dry-run && 'release' || '' }}
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
CARGO_INCREMENTAL: 0
|
||||
@@ -336,7 +345,7 @@ jobs:
|
||||
name: Windows ${{ matrix.arch }}
|
||||
needs: [version]
|
||||
runs-on: windows-latest
|
||||
environment: release
|
||||
environment: ${{ !inputs.dry-run && 'release' || '' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -446,7 +455,7 @@ jobs:
|
||||
needs: [version]
|
||||
# The signing key lives in the release environment, as it does for the macOS, Windows and
|
||||
# flatpak jobs; without this the Linux packages are built unsigned.
|
||||
environment: release
|
||||
environment: ${{ !inputs.dry-run && 'release' || '' }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -543,7 +552,7 @@ jobs:
|
||||
needs: [version, linux]
|
||||
runs-on: ${{ matrix.runner }}
|
||||
# LINUX_SIGNING_KEY comes from the repo's release environment, as the macOS secrets do.
|
||||
environment: release
|
||||
environment: ${{ !inputs.dry-run && 'release' || '' }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -619,7 +628,7 @@ jobs:
|
||||
packaging/linux/flatpak-bundle.sh "$tarball"
|
||||
printf 'tarball=%s\n' "$tarball" >> "$GITHUB_OUTPUT"
|
||||
- name: Publish Flatpak OCI layout to GHCR and Docker Hub
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name != 'pull_request' && !inputs.dry-run
|
||||
env:
|
||||
RELEASE_VERSION: ${{ needs.version.outputs.version }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
@@ -1051,7 +1060,7 @@ jobs:
|
||||
name: Linux riscv64
|
||||
if: inputs.has-riscv64
|
||||
needs: [version]
|
||||
environment: release
|
||||
environment: ${{ !inputs.dry-run && 'release' || '' }}
|
||||
# Not 22.04 like the other Linux jobs: Ubuntu never built jammy's ncurses security update for
|
||||
# riscv64, so the amd64 and riscv64 libtinfo6 can't match and the cross deps don't install (#44).
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -1217,10 +1226,10 @@ jobs:
|
||||
release:
|
||||
timeout-minutes: 10
|
||||
name: Draft GitHub Release
|
||||
if: "!cancelled() && !contains(needs.*.result, 'failure')"
|
||||
if: "!inputs.dry-run && !cancelled() && !contains(needs.*.result, 'failure')"
|
||||
needs: [version, macos, windows, linux, linux-riscv64, flatpak, arch, freebsd, web, server]
|
||||
runs-on: ubuntu-24.04
|
||||
environment: release
|
||||
environment: ${{ !inputs.dry-run && 'release' || '' }}
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
"""release.yml's dry-run input: a nightly run on main builds and checks but releases nothing."""
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
import yaml
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DATA = yaml.load((ROOT / '.github/workflows/release.yml').read_text(), Loader=yaml.BaseLoader)
|
||||
JOBS = DATA['jobs']
|
||||
DRY = '!inputs.dry-run'
|
||||
|
||||
|
||||
class DryRunTests(unittest.TestCase):
|
||||
def test_the_input_defaults_to_a_real_release(self):
|
||||
spec = DATA['on']['workflow_call']['inputs']['dry-run']
|
||||
self.assertEqual((spec['type'], spec['default']), ('boolean', 'false'))
|
||||
|
||||
def test_no_job_enters_the_release_environment_on_a_dry_run(self):
|
||||
# The environment holds the signing secrets and only admits the release branch.
|
||||
for name, job in JOBS.items():
|
||||
env = job.get('environment')
|
||||
if env is not None:
|
||||
self.assertIn(DRY, env, name)
|
||||
self.assertNotEqual(env.strip(), 'release', name)
|
||||
|
||||
def test_the_draft_and_macos_are_skipped(self):
|
||||
# The draft is the release; macOS runs on a paid larger runner.
|
||||
for name in ('release', 'macos'):
|
||||
self.assertIn(DRY, JOBS[name].get('if', ''), name)
|
||||
|
||||
def test_nothing_is_pushed_to_a_registry(self):
|
||||
for name, job in JOBS.items():
|
||||
for step in job.get('steps', []):
|
||||
if 'skopeo copy' in step.get('run', '') or 'docker push' in step.get('run', ''):
|
||||
self.assertIn(DRY, step.get('if', ''), f"{name}: {step.get('name')}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -98,8 +98,8 @@ class FlatpakOciPublishTests(unittest.TestCase):
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
self.assertEqual(self.log.read_text(), "")
|
||||
|
||||
def test_the_step_never_runs_for_a_pull_request(self):
|
||||
self.assertEqual(STEP.get("if"), "github.event_name != 'pull_request'")
|
||||
def test_the_step_never_runs_for_a_pull_request_or_a_dry_run(self):
|
||||
self.assertEqual(STEP.get("if"), "github.event_name != 'pull_request' && !inputs.dry-run")
|
||||
|
||||
def test_dockerhub_credentials_trigger_dual_push_for_stable_release(self):
|
||||
result = self.publish("1.2.0", "refs/heads/release", DOCKERHUB_USERNAME="user", DOCKERHUB_TOKEN="secret")
|
||||
|
||||
@@ -156,7 +156,8 @@ class SigningWiringTests(unittest.TestCase):
|
||||
|
||||
def test_the_flatpak_job_imports_the_key_before_building_the_bundle(self):
|
||||
job = WORKFLOW["jobs"]["flatpak"]
|
||||
self.assertEqual(job["environment"], "release")
|
||||
# The release environment holds the signing key; a dry run (release.yml's dry-run) stays out.
|
||||
self.assertEqual(job["environment"], "${{ !inputs.dry-run && 'release' || '' }}")
|
||||
uses = [s.get("uses", "") for s in job["steps"]]
|
||||
names = [s.get("name") for s in job["steps"]]
|
||||
imported = next(i for i, u in enumerate(uses) if u.startswith("storytold/craft-common-actions/actions/import-signing-key@"))
|
||||
|
||||
Reference in new issue
Block a user