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
49 changes: 0 additions & 49 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ on:
description: Existing version tag (vX.Y.Z) committed through a reviewed PR
type: string
required: true
release_mode:
description: Use the ordinary release or reviewed-epic admission
type: choice
options: [main, reviewed-epic]
default: main
required: true
reviewed_pr:
description: Positive canonical PR number whose merge commit the tag names (reviewed-epic only)
type: number
required: false
push:
tags: ['v*']
permissions: {}
Expand All @@ -28,15 +18,11 @@ jobs:
outputs:
tag: ${{ steps.tag.outputs.tag }}
version: ${{ steps.tag.outputs.version }}
release_mode: ${{ steps.tag.outputs.release_mode }}
reviewed_pr: ${{ steps.tag.outputs.reviewed_pr }}
steps:
- id: tag
shell: bash
env:
TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.tag }}
RELEASE_MODE: ${{ github.event_name == 'push' && 'main' || inputs.release_mode }}
REVIEWED_PR: ${{ inputs.reviewed_pr }}
run: |
set -euo pipefail
[[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([+-][0-9A-Za-z.-]+)?$ ]] || {
Expand All @@ -45,47 +31,12 @@ jobs:
}
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
[[ "$RELEASE_MODE" == main || "$RELEASE_MODE" == reviewed-epic ]] || {
echo "release_mode must be main or reviewed-epic" >&2
exit 2
}
if [[ "$RELEASE_MODE" == reviewed-epic ]]; then
[[ "$REVIEWED_PR" =~ ^[1-9][0-9]*$ ]] || {
echo "reviewed_pr must be a positive integer in reviewed-epic mode" >&2
exit 2
}
else
[[ -z "$REVIEWED_PR" || "$REVIEWED_PR" == 0 ]] || {
echo "reviewed_pr is only valid in reviewed-epic mode" >&2
exit 2
}
REVIEWED_PR=""
fi
{
echo "release_mode=$RELEASE_MODE"
# The reusable workflow input is numeric; zero is the ordinary-path sentinel.
echo "reviewed_pr=${REVIEWED_PR:-0}"
} >> "$GITHUB_OUTPUT"
module-release:
needs: resolve
if: needs.resolve.outputs.release_mode == 'main'
permissions:
contents: write
uses: tinyhumansai/.github/.github/workflows/module-release.yml@4adc1080fb495098e7af1aade82ed7e6e3c69bb7
with:
tag: ${{ needs.resolve.outputs.tag }}
version: ${{ needs.resolve.outputs.version }}
module-crate: tinysearch
module-reviewed-epic-release:
needs: resolve
if: needs.resolve.outputs.release_mode == 'reviewed-epic'
permissions:
contents: write
pull-requests: read
checks: read
actions: read
uses: tinyhumansai/.github/.github/workflows/module-reviewed-epic-release.yml@6ed83b04aab2d8977ec62e966cb914531e534fa4
with:
tag: ${{ needs.resolve.outputs.tag }}
version: ${{ needs.resolve.outputs.version }}
reviewed-pr: ${{ fromJSON(needs.resolve.outputs.reviewed_pr) }}
68 changes: 22 additions & 46 deletions scripts/test-release-workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
ROOT = Path(__file__).resolve().parent.parent
WORKFLOW = ROOT / ".github/workflows/release.yml"
CI_WORKFLOW = ROOT / ".github/workflows/ci.yml"
REVIEWED_RELEASE_SHA = "6ed83b04aab2d8977ec62e966cb914531e534fa4"
ORDINARY_RELEASE_SHA = "4adc1080fb495098e7af1aade82ed7e6e3c69bb7"
TINYBUS_SDK_SHA = "34d3bd6dda099e54cee11a2f96f28a21da9e0759"

Expand Down Expand Up @@ -49,16 +48,15 @@ def setUpClass(cls):
cls.ci_workflow = CI_WORKFLOW.read_text()
cls.script = resolve_script(cls.workflow)

def run_resolve(self, mode="main", reviewed_pr="", ref="refs/heads/main"):
def run_resolve(self, ref="refs/heads/main", **extra):
with tempfile.TemporaryDirectory() as directory:
output = Path(directory) / "output"
env = dict(
os.environ,
TAG="v0.5.2",
RELEASE_MODE=mode,
REVIEWED_PR=reviewed_pr,
GITHUB_REF=ref,
GITHUB_OUTPUT=str(output),
**extra,
)
result = subprocess.run(
["bash", "-c", self.script],
Expand All @@ -71,11 +69,9 @@ def run_resolve(self, mode="main", reviewed_pr="", ref="refs/heads/main"):
def test_ordinary_tag_release_route_and_module_ci_pin_are_preserved(self):
self.assertIn("push:\n tags: ['v*']", self.workflow)
self.assertIn("github.event_name == 'push' && github.ref_name || inputs.tag", self.workflow)
self.assertIn(
"github.event_name == 'push' && 'main' || inputs.release_mode",
self.workflow,
)
self.assertIn("release_mode=main", self.run_resolve("main")[1])
result, output = self.run_resolve()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(output, "tag=v0.5.2\nversion=0.5.2\n")
self.assertIn(
f"uses: tinyhumansai/.github/.github/workflows/module-release.yml@{ORDINARY_RELEASE_SHA}",
self.workflow,
Expand Down Expand Up @@ -130,32 +126,14 @@ def test_sdk_gitlink_guard_accepts_exact_and_rejects_stale_or_missing_pins(self)
)
)

def test_reviewed_release_requires_positive_pr_on_main_and_uses_fixed_profile(self):
result, output = self.run_resolve("reviewed-epic", "83")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("tag=v0.5.2", output)
self.assertIn("version=0.5.2", output)
self.assertIn("release_mode=reviewed-epic", output)
self.assertIn("reviewed_pr=83", output)
self.assertIn(
"module-reviewed-epic-release.yml@" + REVIEWED_RELEASE_SHA,
self.workflow,
)
reviewed_job = self.workflow.split(" module-reviewed-epic-release:\n", 1)[1]
self.assertIn("pull-requests: read", reviewed_job)
self.assertIn("checks: read", reviewed_job)
self.assertIn("actions: read", reviewed_job)
ordinary_job = self.workflow.split(" module-release:\n", 1)[1].split(
" module-reviewed-epic-release:", 1
)[0]
self.assertIn("module-crate: tinysearch", ordinary_job)
self.assertIn(
"reviewed-pr: ${{ fromJSON(needs.resolve.outputs.reviewed_pr)",
reviewed_job,
)
self.assertNotIn("module-crate:", reviewed_job)
self.assertNotIn("asset-name:", reviewed_job)
self.assertNotIn("apt-packages:", reviewed_job)
def test_a_dispatch_names_only_a_tag_and_no_reviewed_epic_path_remains(self):
# Releases come only from official main, so there is no mode to choose.
inputs = self.workflow.split(" inputs:\n", 1)[1].split(" push:\n", 1)[0]
self.assertEqual(re.findall(r"(?m)^ (\w+):$", inputs), ["tag"])
self.assertNotIn("reviewed-epic", self.workflow)
self.assertNotIn("reviewed_pr", self.workflow)
self.assertNotIn("release_mode", self.workflow)
self.assertEqual(self.workflow.count("uses: tinyhumansai/.github/"), 1)

def test_resolve_script_stops_at_the_end_of_its_run_block(self):
workflow = (
Expand All @@ -164,20 +142,18 @@ def test_resolve_script_stops_at_the_end_of_its_run_block(self):
)
self.assertEqual(resolve_script(workflow).strip(), "echo resolve")

def test_reviewed_release_rejects_missing_zero_and_noninteger_pr(self):
for reviewed_pr in ("", "0", "-1", "1.5", "one"):
with self.subTest(reviewed_pr=reviewed_pr):
result, _ = self.run_resolve("reviewed-epic", reviewed_pr)
self.assertNotEqual(result.returncode, 0)

def test_reviewed_release_accepts_dispatch_from_canonical_epic_branch(self):
def test_an_epic_dispatch_is_refused_a_reviewed_release(self):
# The old inputs are ignored: the resolver only names the tag, and the
# one release job is the ordinary module release.
result, output = self.run_resolve(
"reviewed-epic", "83", "refs/heads/epic/8056-modules-wiring"
"refs/heads/epic/8056-modules-wiring",
RELEASE_MODE="reviewed-epic",
REVIEWED_PR="83",
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("release_mode=reviewed-epic", output)
self.assertIn("reviewed_pr=83", output)

self.assertEqual(output, "tag=v0.5.2\nversion=0.5.2\n")
jobs = re.findall(r"(?m)^ ([\w-]+):$", self.workflow.split("\njobs:\n", 1)[1])
self.assertEqual(jobs, ["resolve", "module-release"])

if __name__ == "__main__":
unittest.main()
Loading