diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index ab45716..aee4c53 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -66,7 +66,8 @@ jobs: GH_TOKEN: ${{ github.token }} TAG: ${{ inputs.tag }} run: | - if [ "$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName --jq .tagName)" = "$TAG" ]; then + latest="$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName --jq .tagName)" + if [ "$latest" = "$TAG" ]; then echo "latest=true" >> "$GITHUB_OUTPUT" else echo "skip=--skip=homebrew,scoop,aur" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8fadd51..55b81ef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,7 @@ jobs: else echo "code=true" >> "$GITHUB_OUTPUT" fi - if git diff --quiet "$base"...HEAD -- release-tooling Dockerfile .dockerignore LICENSE DATA-LICENSES.md .github/workflows/packages.yml .github/workflows/test.yml; then + if git diff --quiet "$base"...HEAD -- '*.go' go.mod go.sum release-tooling Dockerfile .dockerignore LICENSE DATA-LICENSES.md .github/workflows/packages.yml .github/workflows/test.yml; then echo "packaging=false" >> "$GITHUB_OUTPUT" else echo "packaging=true" >> "$GITHUB_OUTPUT" diff --git a/README.md b/README.md index 40efeb1..16cf713 100644 --- a/README.md +++ b/README.md @@ -1219,9 +1219,10 @@ docker build --build-arg GO_VERSION=1.22.12 --target portable . # lowest support GO_VERSION=1.22.12 docker compose run --rm test # the same tests, without the image build ``` -A change to `release-tooling/`, the `Dockerfile`, `.dockerignore`, the licence files or -either workflow also builds the apt, dnf and apk repositories from snapshot packages, -signs them with throwaway keys, and installs fejkdata from each: +A change to Go code, `release-tooling/`, the `Dockerfile`, `.dockerignore`, the licence +files or either workflow also builds the release binaries for every platform, the apt, dnf +and apk repositories from their packages, signed with throwaway keys, and installs +fejkdata from each: ```sh docker build -f release-tooling/package-repos.Dockerfile --target throwaway-keys --output /tmp/fejkdata-keys . diff --git a/release-tooling/package-repos.Dockerfile b/release-tooling/package-repos.Dockerfile index 35cac22..689a348 100644 --- a/release-tooling/package-repos.Dockerfile +++ b/release-tooling/package-repos.Dockerfile @@ -1,8 +1,4 @@ -# The apt, dnf and apk repositories GitHub Pages serves, signed, from the .deb, .rpm and -# .apk files of the `packages` stage: a snapshot built from the source here, or a release's -# when `--build-context packages=` replaces it. The checks target installs fejkdata -# from each repository, and where EXPECTED_VERSION is set, checks it prints that tag; the -# README's Development section shows the commands. +# A release's packages replace the snapshot ones through `--build-context packages=`. ARG BASE_URL=https://larvit.github.io/fejkdata ARG EXPECTED_VERSION diff --git a/release-tooling/publish_release_test.py b/release-tooling/publish_release_test.py index 285f33d..8368d71 100644 --- a/release-tooling/publish_release_test.py +++ b/release-tooling/publish_release_test.py @@ -16,6 +16,19 @@ def not_found(path): return urllib.error.HTTPError(path, 404, "Not Found", None, None) +def forge(responses, created): + def request(path, data=None): + if data is not None: + created.append(data) + return {"html_url": "https://forge.example/release"} + response = responses.get(path) + if response is None: + raise not_found(path) + return response + + return request + + class TagGuard(unittest.TestCase): def setUp(self): cwd = os.getcwd() @@ -31,17 +44,7 @@ class TagGuard(unittest.TestCase): def publish(self, responses): created = [] - - def request(path, data=None): - if data is not None: - created.append(data) - return {"html_url": "https://forge.example/release"} - response = responses.get(path) - if response is None: - raise not_found(path) - return response - - with mock.patch.object(publish_release, "request", request), \ + with mock.patch.object(publish_release, "request", forge(responses, created)), \ redirect_stdout(io.StringIO()), redirect_stderr(io.StringIO()): code, self.tag = publish_release.publish() return code, created @@ -70,6 +73,22 @@ class TagGuard(unittest.TestCase): self.assertEqual(created, [{"body": "- A change.", "name": "v1.2.3", "tag_name": "v1.2.3", "target_commitish": SHA}]) self.assertEqual(self.tag, "v1.2.3") + def test_an_unreleased_heading_publishes_nothing(self): + with open("CHANGELOG.md", "w", encoding="utf-8") as f: + f.write("# Changelog\n\n## [Unreleased]\n\n- A change.\n") + code, created = self.publish({}) + self.assertEqual((code, created, self.tag), (0, [], None)) + + def test_main_names_only_a_published_tag_to_ci(self): + for responses, output in (({}, "tag=v1.2.3\n"), ({"releases/tags/v1.2.3": {"html_url": "https://forge.example/release"}}, "")): + open("output", "w").close() + with mock.patch.dict(os.environ, {"GITHUB_OUTPUT": os.path.abspath("output")}), \ + mock.patch.object(publish_release, "request", forge(responses, [])), \ + redirect_stdout(io.StringIO()): + self.assertEqual(publish_release.main(), 0) + with open("output", encoding="utf-8") as f: + self.assertEqual(f.read(), output) + def test_a_published_release_publishes_nothing(self): code, created = self.publish({"releases/tags/v1.2.3": {"html_url": "https://forge.example/release"}}) self.assertEqual((code, created, self.tag), (0, [], None))