From b944b5379335b22e4b3f6f4a3f4f21b635fca0f4 Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Mon, 11 May 2026 18:29:17 +1000 Subject: [PATCH 1/8] UID2-6762: Consolidate release-notes pipeline onto shared_create_releases Extend the shared_create_releases composite action to support all five publish platforms (Docker, Maven, PyPI, NuGet, iOS) and consolidate every inline mikepenz/release-changelog-builder step in the shared workflows onto the composite. Net result: one canonical release-notes pipeline (Build Changelog -> Delete Draft Releases -> Create Release draft) in a single composite action, with each workflow calling it via a single ~7-line step instead of ~30 lines of duplicated inline mikepenz/delete-draft/softprops blocks. Side-effect fixes: - PyPI template no longer emits a Maven block (uses pip install instead) and links to the version-specific PyPI page - NuGet template no longer emits a Maven block (uses dotnet add package) and links to the version-specific NuGet page - Every workflow now has Delete Draft Releases (previously only shared-publish-java-to-docker-versioned had it) - shared-publish-to-docker-versioned bumped from @v2 to @v3 for consistency with the rest of the repo Decision and rationale documented in UID2-6762 (mikepenz over GitHub- native: PR-line author suppression for public-facing release pages). --- ...ared-publish-java-to-docker-versioned.yaml | 30 ++----- .../shared-publish-to-docker-versioned.yaml | 2 +- .../shared-publish-to-ios-version.yaml | 22 ++--- .../shared-publish-to-maven-versioned.yaml | 25 ++---- .../shared-publish-to-nuget-versioned.yaml | 25 ++---- .../shared-publish-to-pypi-versioned.yaml | 23 ++--- README.md | 11 +++ actions/shared_create_releases/action.yaml | 86 +++++++++++++------ 8 files changed, 104 insertions(+), 120 deletions(-) diff --git a/.github/workflows/shared-publish-java-to-docker-versioned.yaml b/.github/workflows/shared-publish-java-to-docker-versioned.yaml index 813ef6cc..75d2395a 100644 --- a/.github/workflows/shared-publish-java-to-docker-versioned.yaml +++ b/.github/workflows/shared-publish-java-to-docker-versioned.yaml @@ -224,28 +224,12 @@ jobs: subject_name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}${{ inputs.append_image_name }} subject_digest: ${{ steps.push.outputs.digest }} - - name: Build Changelog - id: github_release - if: ${{ steps.checkRelease.outputs.is_release == 'true' }} - uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 - with: - toTag: v${{ steps.version.outputs.new_version }} - configurationJson: | - { - "template": "#{{CHANGELOG}}\n## Installation\n```\ndocker pull ${{ steps.meta.outputs.tags }}\n```\n\n## Image reference to deploy: \n```\n${{ steps.updatePom.outputs.image_tag }}\n```\n\n## Changelog\n#{{UNCATEGORIZED}}", - "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" - } - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Delete Draft Releases - if: ${{ steps.checkRelease.outputs.is_release == 'true' }} - uses: IABTechLab/uid2-shared-actions/actions/delete_draft_releases@v3 - - name: Create Release - if: ${{ steps.checkRelease.outputs.is_release == 'true' }} - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 + uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: - name: v${{ steps.version.outputs.new_version }} - body: ${{ steps.github_release.outputs.changelog }} - draft: true + is_release: ${{ steps.checkRelease.outputs.is_release }} + new_version: ${{ steps.version.outputs.new_version }} + tags: ${{ steps.meta.outputs.tags }} + image_tag: ${{ steps.updatePom.outputs.image_tag }} + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_platform: Docker diff --git a/.github/workflows/shared-publish-to-docker-versioned.yaml b/.github/workflows/shared-publish-to-docker-versioned.yaml index 559b1d94..8efbdea5 100644 --- a/.github/workflows/shared-publish-to-docker-versioned.yaml +++ b/.github/workflows/shared-publish-to-docker-versioned.yaml @@ -80,7 +80,7 @@ jobs: - name: Create Release id: github_release - uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v2 + uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: is_release: ${{ steps.setup.outputs.is_release }} new_version: ${{ inputs.new_version }} diff --git a/.github/workflows/shared-publish-to-ios-version.yaml b/.github/workflows/shared-publish-to-ios-version.yaml index e56bce26..e34cd234 100644 --- a/.github/workflows/shared-publish-to-ios-version.yaml +++ b/.github/workflows/shared-publish-to-ios-version.yaml @@ -98,22 +98,10 @@ jobs: tag: v${{ steps.version.outputs.new_version }} github_token: ${{ inputs.merge_environment != '' && secrets.GH_MERGE_TOKEN || '' }} - - name: Build Changelog - id: github_release - uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 - with: - toTag: v${{ steps.version.outputs.new_version }} - configurationJson: | - { - "template": "#{{CHANGELOG}}\n## Changelog\n#{{UNCATEGORIZED}}", - "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" - } - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Create Release - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 + uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: - name: v${{ steps.version.outputs.new_version }} - body: ${{ steps.github_release.outputs.changelog }} - draft: true + is_release: ${{ steps.checkRelease.outputs.is_release }} + new_version: ${{ steps.version.outputs.new_version }} + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_platform: iOS diff --git a/.github/workflows/shared-publish-to-maven-versioned.yaml b/.github/workflows/shared-publish-to-maven-versioned.yaml index 1fe1b952..06cefa6e 100644 --- a/.github/workflows/shared-publish-to-maven-versioned.yaml +++ b/.github/workflows/shared-publish-to-maven-versioned.yaml @@ -159,24 +159,11 @@ jobs: tag: v${{ steps.version.outputs.new_version }} github_token: ${{ inputs.merge_environment != '' && secrets.GH_MERGE_TOKEN || '' }} - - name: Build Changelog - id: github_release - if: ${{ env.IS_RELEASE == 'true' }} - uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 - with: - toTag: v${{ steps.version.outputs.new_version }} - configurationJson: | - { - "template": "#{{CHANGELOG}}\n## Maven\n```\n\n com.uid2\n ${{ env.REPO }}\n ${{ steps.version.outputs.new_version }}\n\n```\n\n## Jar Files\n- [${{ env.REPO }}-${{ steps.version.outputs.new_version }}.jar](https://repo1.maven.org/maven2/com/uid2/${{ env.REPO }}/${{ steps.version.outputs.new_version }}/${{ env.REPO }}-${{ steps.version.outputs.new_version }}.jar)\n\n## Changelog\n#{{UNCATEGORIZED}}", - "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" - } - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Create Release - if: ${{ env.IS_RELEASE == 'true' }} - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 + uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: - name: v${{ steps.version.outputs.new_version }} - body: ${{ steps.github_release.outputs.changelog }} - draft: true + is_release: ${{ env.IS_RELEASE }} + new_version: ${{ steps.version.outputs.new_version }} + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_platform: Maven + repo: ${{ env.REPO }} diff --git a/.github/workflows/shared-publish-to-nuget-versioned.yaml b/.github/workflows/shared-publish-to-nuget-versioned.yaml index 19061075..b4a3b64a 100644 --- a/.github/workflows/shared-publish-to-nuget-versioned.yaml +++ b/.github/workflows/shared-publish-to-nuget-versioned.yaml @@ -107,24 +107,11 @@ jobs: tag: v${{ steps.version.outputs.new_version }} github_token: ${{ inputs.merge_environment != '' && secrets.GH_MERGE_TOKEN || '' }} - - name: Build Changelog - if: ${{ steps.checkRelease.outputs.is_release == 'true' }} - id: github_release - uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 - with: - toTag: v${{ steps.version.outputs.new_version }} - configurationJson: | - { - "template": "#{{CHANGELOG}}\n## NuGet\n```\n\n com.uid2\n ${{ env.REPO }}\n ${{ steps.version.outputs.new_version }}\n\n```\n\n## Nuget Files\n- [UID2.Client.${{ steps.version.outputs.new_version }}.nupkg](https://www.nuget.org/packages/UID2.Client)\n\n## Changelog\n#{{UNCATEGORIZED}}", - "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" - } - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Create Release - if: ${{ steps.checkRelease.outputs.is_release == 'true' }} - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 + uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: - name: v${{ steps.version.outputs.new_version }} - body: ${{ steps.github_release.outputs.changelog }} - draft: true + is_release: ${{ steps.checkRelease.outputs.is_release }} + new_version: ${{ steps.version.outputs.new_version }} + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_platform: NuGet + repo: UID2.Client diff --git a/.github/workflows/shared-publish-to-pypi-versioned.yaml b/.github/workflows/shared-publish-to-pypi-versioned.yaml index d0a76467..b7fcc7c4 100644 --- a/.github/workflows/shared-publish-to-pypi-versioned.yaml +++ b/.github/workflows/shared-publish-to-pypi-versioned.yaml @@ -97,22 +97,11 @@ jobs: tag: v${{ steps.version.outputs.new_version }} github_token: ${{ inputs.merge_environment != '' && secrets.GH_MERGE_TOKEN || '' }} - - name: Build Changelog - id: github_release - uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 - with: - toTag: v${{ steps.version.outputs.new_version }} - configurationJson: | - { - "template": "#{{CHANGELOG}}\n## Pypi\n```\n\n com.uid2\n ${{ env.REPO }}\n ${{ steps.version.outputs.new_version }}\n\n```\n\n## Pypi Files\n- [uid2_client-${{ steps.version.outputs.new_version }}.tar.gz](https://pypi.org/project/uid2-client/)\n\n## Changelog\n#{{UNCATEGORIZED}}", - "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" - } - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Create Release - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 + uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: - name: v${{ steps.version.outputs.new_version }} - body: ${{ steps.github_release.outputs.changelog }} - draft: true + is_release: ${{ steps.checkRelease.outputs.is_release }} + new_version: ${{ steps.version.outputs.new_version }} + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_platform: PyPI + repo: ${{ env.REPO }} diff --git a/README.md b/README.md index 2b12b632..ce5d3cf5 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,17 @@ This repo contains shared actions and workflows that are consumed by the other u This simplifies the management and maintenance of the workflows. +## Release notes + +All shared publish workflows generate release notes via the `actions/shared_create_releases` composite action, which wraps [`mikepenz/release-changelog-builder-action`](https://github.com/mikepenz/release-changelog-builder-action) (SHA-pinned). This is the canonical approach for this repo — chosen over GitHub-native auto-generated notes (`generate_release_notes: true`) because: + +- The native format hardcodes `* TITLE by @AUTHOR in #NUMBER`. Authors are noise to the public consumers of these releases; mikepenz's `pr_template` lets us emit `- TITLE - ( PR: #NUMBER )` instead. +- The composite embeds a per-platform install snippet (`docker pull`, `pip install`, `dotnet add package`, Maven ``) above the changelog. + +`shared_create_releases` supports `publish_platform` values `Docker`, `Maven`, `PyPI`, `NuGet`, `iOS`. It runs three steps internally: Build Changelog (mikepenz) → Delete Draft Releases → Create Release (softprops, draft). When `is_release` is `false` (Snapshot/pre-release) the action is a no-op, so callers can invoke it unconditionally. + +When adding a new publish workflow, call `IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3` rather than inlining mikepenz. Do not set `continue-on-error: true` on it — the workflow must fail if release-notes generation fails. Decision documented in [UID2-6762](https://thetradedesk.atlassian.net/browse/UID2-6762). + ## Tips and tricks If you're trying to do something that should be simple, but can't find something that quite supports what you're trying to do, the [GitHub Script action](https://github.com/actions/github-script) gives you an authenticated GitHub API client and you can just provide a JavaScript script. For an example, see the "Tag commit" step in the [Commit, PR, and Merge](actions\commit-pr-and-merge\action.yaml) shared action. diff --git a/actions/shared_create_releases/action.yaml b/actions/shared_create_releases/action.yaml index 83aae3ec..19bf2a6f 100644 --- a/actions/shared_create_releases/action.yaml +++ b/actions/shared_create_releases/action.yaml @@ -1,36 +1,36 @@ name: Create releases -description: Create releases and build changelogs +description: Build the release-notes changelog, delete stale draft releases, and create a draft GitHub Release for a published artifact. Canonical release-notes pipeline for this repo — every shared publish workflow should call this action rather than inlining mikepenz/release-changelog-builder. Decision and rationale documented in UID2-6762. inputs: is_release: - description: True if a release should be created + description: True if a release should be created (Patch/Minor/Major). When false, the action is a no-op — safe to call unconditionally for Snapshot/pre-release builds. default: 'false' new_version: - description: The new version number to be incremented to + description: The new version number being released (without leading v). required: true - tags: - description: The docker image tags - default: '' - image_tag: - description: The image tag for the new version - default: '' github_token: - description: The github token to login to Docker container + description: GitHub token used by mikepenz to read merged PRs and by softprops to create the draft release. required: true publish_platform: - description: The platform we are publishing to. Must be one of [Docker or Maven] + description: Must be one of [Docker, Maven, PyPI, NuGet, iOS]. required: true repo: - description: The repo that publishing to. + description: Package/artifact identifier. Used by Maven (artifactId in the dependency snippet and jar URL), PyPI (pip install target and PyPI page link), and NuGet (package id). Not used by Docker or iOS. + default: '' + tags: + description: Comma-separated docker image tags (Docker only). Typically the output of docker/metadata-action. + default: '' + image_tag: + description: The image reference shown in the release notes as the deploy target (Docker only). default: '' runs: - using: "composite" + using: "composite" steps: - name: Build Docker Changelog id: github_release_docker - if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'Docker'}} + if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'Docker' }} uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: toTag: v${{ inputs.new_version }} @@ -44,7 +44,7 @@ runs: - name: Build Maven Changelog id: github_release_maven - if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'Maven'}} + if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'Maven' }} uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: toTag: v${{ inputs.new_version }} @@ -56,18 +56,56 @@ runs: env: GITHUB_TOKEN: ${{ inputs.github_token }} - - name: Create Docker Release - if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'Docker' }} - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 + - name: Build PyPI Changelog + id: github_release_pypi + if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'PyPI' }} + uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: - name: v${{ inputs.new_version }} - body: ${{ steps.github_release_docker.outputs.changelog }} - draft: true + toTag: v${{ inputs.new_version }} + configurationJson: | + { + "template": "#{{CHANGELOG}}\n## PyPI\n```\npip install ${{ inputs.repo }}==${{ inputs.new_version }}\n```\n\n## PyPI page\n- [${{ inputs.repo }} ${{ inputs.new_version }}](https://pypi.org/project/${{ inputs.repo }}/${{ inputs.new_version }}/)\n\n## Changelog\n#{{UNCATEGORIZED}}", + "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" + } + env: + GITHUB_TOKEN: ${{ inputs.github_token }} + + - name: Build NuGet Changelog + id: github_release_nuget + if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'NuGet' }} + uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 + with: + toTag: v${{ inputs.new_version }} + configurationJson: | + { + "template": "#{{CHANGELOG}}\n## NuGet\n```\ndotnet add package ${{ inputs.repo }} --version ${{ inputs.new_version }}\n```\n\n## NuGet page\n- [${{ inputs.repo }} ${{ inputs.new_version }}](https://www.nuget.org/packages/${{ inputs.repo }}/${{ inputs.new_version }})\n\n## Changelog\n#{{UNCATEGORIZED}}", + "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" + } + env: + GITHUB_TOKEN: ${{ inputs.github_token }} + + - name: Build iOS Changelog + id: github_release_ios + if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'iOS' }} + uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 + with: + toTag: v${{ inputs.new_version }} + configurationJson: | + { + "template": "#{{CHANGELOG}}\n## Changelog\n#{{UNCATEGORIZED}}", + "pr_template": " - #{{TITLE}} - ( PR: ##{{NUMBER}} )" + } + env: + GITHUB_TOKEN: ${{ inputs.github_token }} + + - name: Delete Draft Releases + if: ${{ inputs.is_release == 'true' }} + uses: IABTechLab/uid2-shared-actions/actions/delete_draft_releases@v3 - - name: Create Maven Release - if: ${{ inputs.is_release == 'true' && inputs.publish_platform == 'Maven'}} + - name: Create Release + if: ${{ inputs.is_release == 'true' }} uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: name: v${{ inputs.new_version }} - body: ${{ steps.github_release_maven.outputs.changelog }} + body: ${{ inputs.publish_platform == 'Docker' && steps.github_release_docker.outputs.changelog || inputs.publish_platform == 'Maven' && steps.github_release_maven.outputs.changelog || inputs.publish_platform == 'PyPI' && steps.github_release_pypi.outputs.changelog || inputs.publish_platform == 'NuGet' && steps.github_release_nuget.outputs.changelog || steps.github_release_ios.outputs.changelog }} draft: true From 200a5191b5a1c2776d7f45d3c94070e54da3b69d Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Tue, 12 May 2026 11:04:38 +1000 Subject: [PATCH 2/8] UID2-6762: Add temporary smoke workflow for shared_create_releases workflow_dispatch harness exercising each platform branch of the composite against an existing v3 tag so we can inspect the resulting draft-release body before merge. Delete this file and any draft releases it produces once verification is complete. --- .github/workflows/smoke-create-releases.yaml | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/smoke-create-releases.yaml diff --git a/.github/workflows/smoke-create-releases.yaml b/.github/workflows/smoke-create-releases.yaml new file mode 100644 index 00000000..d63f9af3 --- /dev/null +++ b/.github/workflows/smoke-create-releases.yaml @@ -0,0 +1,47 @@ +name: Smoke test shared_create_releases (TEMPORARY) +# Temporary smoke harness for UID2-6762 / PR #229. Exercises each platform +# branch of actions/shared_create_releases against an existing v3 tag so we +# can inspect the resulting draft-release body before merge. Delete this file +# and any draft releases it produces once verification is complete. + +on: + workflow_dispatch: + inputs: + platform: + description: Platform to exercise + required: true + type: choice + options: + - Docker + - Maven + - PyPI + - NuGet + - iOS + to_tag_version: + description: Existing v tag in this repo to use as toTag (mikepenz needs an existing tag to compare against). + required: true + type: string + default: '3.82' + +jobs: + smoke: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Smoke shared_create_releases + uses: ./actions/shared_create_releases + with: + is_release: 'true' + new_version: ${{ inputs.to_tag_version }} + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_platform: ${{ inputs.platform }} + # Mock inputs — only consumed by the matching platform branch: + tags: 'ghcr.io/iabtechlab/uid2-smoke-fake:smoke' + image_tag: 'uid2-smoke-fake:smoke' + repo: ${{ inputs.platform == 'NuGet' && 'UID2.Client' || 'uid2-smoke-fake' }} From ed7bbc995e5c745ba26c009f388c7eb6b0e7c05d Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Tue, 12 May 2026 11:08:01 +1000 Subject: [PATCH 3/8] UID2-6762: switch smoke harness to push+matrix trigger --- .github/workflows/smoke-create-releases.yaml | 50 ++++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/.github/workflows/smoke-create-releases.yaml b/.github/workflows/smoke-create-releases.yaml index d63f9af3..15ab6221 100644 --- a/.github/workflows/smoke-create-releases.yaml +++ b/.github/workflows/smoke-create-releases.yaml @@ -5,26 +5,22 @@ name: Smoke test shared_create_releases (TEMPORARY) # and any draft releases it produces once verification is complete. on: - workflow_dispatch: - inputs: - platform: - description: Platform to exercise - required: true - type: choice - options: - - Docker - - Maven - - PyPI - - NuGet - - iOS - to_tag_version: - description: Existing v tag in this repo to use as toTag (mikepenz needs an existing tag to compare against). - required: true - type: string - default: '3.82' + push: + branches: + - jon-UID2-6762-consolidate-release-notes + paths: + - .github/workflows/smoke-create-releases.yaml + +env: + TO_TAG_VERSION: '3.82' jobs: smoke: + strategy: + fail-fast: false + max-parallel: 1 + matrix: + platform: [Docker, Maven, PyPI, NuGet, iOS] runs-on: ubuntu-latest permissions: contents: write @@ -34,14 +30,26 @@ jobs: with: fetch-depth: 0 - - name: Smoke shared_create_releases + - name: Smoke shared_create_releases (${{ matrix.platform }}) uses: ./actions/shared_create_releases with: is_release: 'true' - new_version: ${{ inputs.to_tag_version }} + new_version: ${{ env.TO_TAG_VERSION }} github_token: ${{ secrets.GITHUB_TOKEN }} - publish_platform: ${{ inputs.platform }} + publish_platform: ${{ matrix.platform }} # Mock inputs — only consumed by the matching platform branch: tags: 'ghcr.io/iabtechlab/uid2-smoke-fake:smoke' image_tag: 'uid2-smoke-fake:smoke' - repo: ${{ inputs.platform == 'NuGet' && 'UID2.Client' || 'uid2-smoke-fake' }} + repo: ${{ matrix.platform == 'NuGet' && 'UID2.Client' || 'uid2-smoke-fake' }} + + - name: Dump draft release body for ${{ matrix.platform }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "=== Draft release body (${{ matrix.platform }}) ===" + # Find the latest draft release matching this version tag and print its body. + gh release list --limit 20 --json tagName,isDraft,name,createdAt \ + --jq '[.[] | select(.isDraft and .name == "v${{ env.TO_TAG_VERSION }}")] | sort_by(.createdAt) | last' + echo "--- body ---" + gh release view "v${{ env.TO_TAG_VERSION }}" --json body --jq .body + echo "=== end ===" From aa379813785cfcdccd81169da564ee2caeb5e030 Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Tue, 12 May 2026 11:18:07 +1000 Subject: [PATCH 4/8] UID2-6762: smoke dump step queries draft by release id, not tag --- .github/workflows/smoke-create-releases.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/smoke-create-releases.yaml b/.github/workflows/smoke-create-releases.yaml index 15ab6221..c888eae8 100644 --- a/.github/workflows/smoke-create-releases.yaml +++ b/.github/workflows/smoke-create-releases.yaml @@ -47,9 +47,12 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "=== Draft release body (${{ matrix.platform }}) ===" - # Find the latest draft release matching this version tag and print its body. - gh release list --limit 20 --json tagName,isDraft,name,createdAt \ - --jq '[.[] | select(.isDraft and .name == "v${{ env.TO_TAG_VERSION }}")] | sort_by(.createdAt) | last' + # `gh release view` resolves by tag — but drafts have no tag, so it'd + # return the published v3.82 release instead. Fetch the latest draft + # by release ID via the API instead. + release_id=$(gh api "repos/${GITHUB_REPOSITORY}/releases" \ + --jq "[.[] | select(.draft and .name == \"v${TO_TAG_VERSION}\")] | sort_by(.created_at) | last | .id") + echo "Draft release id: $release_id" echo "--- body ---" - gh release view "v${{ env.TO_TAG_VERSION }}" --json body --jq .body + gh api "repos/${GITHUB_REPOSITORY}/releases/${release_id}" --jq .body echo "=== end ===" From a5667cc79e1ba91de7cd468a183b9342e0bac871 Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Tue, 12 May 2026 11:36:25 +1000 Subject: [PATCH 5/8] UID2-6762: smoke marks drafts with --editing-- so all 5 survive --- .github/workflows/smoke-create-releases.yaml | 24 +++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/smoke-create-releases.yaml b/.github/workflows/smoke-create-releases.yaml index c888eae8..949d9c1d 100644 --- a/.github/workflows/smoke-create-releases.yaml +++ b/.github/workflows/smoke-create-releases.yaml @@ -42,17 +42,25 @@ jobs: image_tag: 'uid2-smoke-fake:smoke' repo: ${{ matrix.platform == 'NuGet' && 'UID2.Client' || 'uid2-smoke-fake' }} - - name: Dump draft release body for ${{ matrix.platform }} + - name: Tag draft and dump body for ${{ matrix.platform }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PLATFORM: ${{ matrix.platform }} run: | - echo "=== Draft release body (${{ matrix.platform }}) ===" - # `gh release view` resolves by tag — but drafts have no tag, so it'd - # return the published v3.82 release instead. Fetch the latest draft - # by release ID via the API instead. + # Drafts have no tag — `gh release view "v..."` returns the published + # release. Fetch the latest draft by ID via the API instead. release_id=$(gh api "repos/${GITHUB_REPOSITORY}/releases" \ - --jq "[.[] | select(.draft and .name == \"v${TO_TAG_VERSION}\")] | sort_by(.created_at) | last | .id") + --jq "[.[] | select(.draft and (.name | startswith(\"v${TO_TAG_VERSION}\")))] | sort_by(.created_at) | last | .id") echo "Draft release id: $release_id" - echo "--- body ---" - gh api "repos/${GITHUB_REPOSITORY}/releases/${release_id}" --jq .body + # Prepend a marker that delete_draft_releases skips ("--editing--"), + # and rename the draft so each platform's smoke draft is preserved + # for review across matrix iterations. + body=$(gh api "repos/${GITHUB_REPOSITORY}/releases/${release_id}" --jq .body) + marked_body=$'--editing--\n[smoke '"$PLATFORM"$']\n\n'"$body" + gh api -X PATCH "repos/${GITHUB_REPOSITORY}/releases/${release_id}" \ + -f name="v${TO_TAG_VERSION} (smoke ${PLATFORM})" \ + -f body="$marked_body" \ + --jq '"Patched draft: \(.html_url)"' + echo "=== Draft release body (${PLATFORM}) ===" + echo "$body" echo "=== end ===" From 5ba1d27c9fa38ee8623ecca2552509d5787fc675 Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Tue, 12 May 2026 12:09:20 +1000 Subject: [PATCH 6/8] =?UTF-8?q?UID2-6762:=20composite=20supports=20from=5F?= =?UTF-8?q?tag=20override;=20smoke=20uses=20v3.81=E2=86=92v3.82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/smoke-create-releases.yaml | 2 ++ actions/shared_create_releases/action.yaml | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/smoke-create-releases.yaml b/.github/workflows/smoke-create-releases.yaml index 949d9c1d..b26482b0 100644 --- a/.github/workflows/smoke-create-releases.yaml +++ b/.github/workflows/smoke-create-releases.yaml @@ -13,6 +13,7 @@ on: env: TO_TAG_VERSION: '3.82' + FROM_TAG: 'v3.81' jobs: smoke: @@ -35,6 +36,7 @@ jobs: with: is_release: 'true' new_version: ${{ env.TO_TAG_VERSION }} + from_tag: ${{ env.FROM_TAG }} github_token: ${{ secrets.GITHUB_TOKEN }} publish_platform: ${{ matrix.platform }} # Mock inputs — only consumed by the matching platform branch: diff --git a/actions/shared_create_releases/action.yaml b/actions/shared_create_releases/action.yaml index 19bf2a6f..592fbe3c 100644 --- a/actions/shared_create_releases/action.yaml +++ b/actions/shared_create_releases/action.yaml @@ -23,6 +23,9 @@ inputs: image_tag: description: The image reference shown in the release notes as the deploy target (Docker only). default: '' + from_tag: + description: Optional. Override mikepenz's auto-detection of the previous tag. Useful when auto-detection is confused by non-sequential tag names (e.g. when v3.7 and v3.70 coexist) or when manually backfilling notes for a specific tag range. Leave empty in normal release flows. + default: '' runs: using: "composite" @@ -34,6 +37,7 @@ runs: uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: toTag: v${{ inputs.new_version }} + fromTag: ${{ inputs.from_tag }} configurationJson: | { "template": "#{{CHANGELOG}}\n## Installation\n```\ndocker pull ${{ inputs.tags }}\n```\n\n## Image reference to deploy: \n```\n${{ inputs.image_tag }}\n```\n\n## Changelog\n#{{UNCATEGORIZED}}", @@ -48,6 +52,7 @@ runs: uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: toTag: v${{ inputs.new_version }} + fromTag: ${{ inputs.from_tag }} configurationJson: | { "template": "#{{CHANGELOG}}\n## Maven\n```\n\n com.uid2\n ${{ inputs.repo }}\n ${{ inputs.new_version }}\n\n```\n\n## Jar Files\n- [${{ inputs.repo }}-${{ inputs.new_version }}.jar](https://repo1.maven.org/maven2/com/uid2/${{ inputs.repo }}/${{ inputs.new_version }}/${{ inputs.repo }}-${{ inputs.new_version }}.jar)\n\n## Changelog\n#{{UNCATEGORIZED}}", @@ -62,6 +67,7 @@ runs: uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: toTag: v${{ inputs.new_version }} + fromTag: ${{ inputs.from_tag }} configurationJson: | { "template": "#{{CHANGELOG}}\n## PyPI\n```\npip install ${{ inputs.repo }}==${{ inputs.new_version }}\n```\n\n## PyPI page\n- [${{ inputs.repo }} ${{ inputs.new_version }}](https://pypi.org/project/${{ inputs.repo }}/${{ inputs.new_version }}/)\n\n## Changelog\n#{{UNCATEGORIZED}}", @@ -76,6 +82,7 @@ runs: uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: toTag: v${{ inputs.new_version }} + fromTag: ${{ inputs.from_tag }} configurationJson: | { "template": "#{{CHANGELOG}}\n## NuGet\n```\ndotnet add package ${{ inputs.repo }} --version ${{ inputs.new_version }}\n```\n\n## NuGet page\n- [${{ inputs.repo }} ${{ inputs.new_version }}](https://www.nuget.org/packages/${{ inputs.repo }}/${{ inputs.new_version }})\n\n## Changelog\n#{{UNCATEGORIZED}}", @@ -90,6 +97,7 @@ runs: uses: mikepenz/release-changelog-builder-action@32e3c96f29a6532607f638797455e9e98cfc703d # v4 with: toTag: v${{ inputs.new_version }} + fromTag: ${{ inputs.from_tag }} configurationJson: | { "template": "#{{CHANGELOG}}\n## Changelog\n#{{UNCATEGORIZED}}", From e29388e6e94efb87a3c7d802b327fc009dcf47d7 Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Tue, 12 May 2026 14:58:29 +1000 Subject: [PATCH 7/8] UID2-6762: drop smoke harness; keep composite from_tag input --- .github/workflows/smoke-create-releases.yaml | 68 -------------------- 1 file changed, 68 deletions(-) delete mode 100644 .github/workflows/smoke-create-releases.yaml diff --git a/.github/workflows/smoke-create-releases.yaml b/.github/workflows/smoke-create-releases.yaml deleted file mode 100644 index b26482b0..00000000 --- a/.github/workflows/smoke-create-releases.yaml +++ /dev/null @@ -1,68 +0,0 @@ -name: Smoke test shared_create_releases (TEMPORARY) -# Temporary smoke harness for UID2-6762 / PR #229. Exercises each platform -# branch of actions/shared_create_releases against an existing v3 tag so we -# can inspect the resulting draft-release body before merge. Delete this file -# and any draft releases it produces once verification is complete. - -on: - push: - branches: - - jon-UID2-6762-consolidate-release-notes - paths: - - .github/workflows/smoke-create-releases.yaml - -env: - TO_TAG_VERSION: '3.82' - FROM_TAG: 'v3.81' - -jobs: - smoke: - strategy: - fail-fast: false - max-parallel: 1 - matrix: - platform: [Docker, Maven, PyPI, NuGet, iOS] - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Smoke shared_create_releases (${{ matrix.platform }}) - uses: ./actions/shared_create_releases - with: - is_release: 'true' - new_version: ${{ env.TO_TAG_VERSION }} - from_tag: ${{ env.FROM_TAG }} - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_platform: ${{ matrix.platform }} - # Mock inputs — only consumed by the matching platform branch: - tags: 'ghcr.io/iabtechlab/uid2-smoke-fake:smoke' - image_tag: 'uid2-smoke-fake:smoke' - repo: ${{ matrix.platform == 'NuGet' && 'UID2.Client' || 'uid2-smoke-fake' }} - - - name: Tag draft and dump body for ${{ matrix.platform }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PLATFORM: ${{ matrix.platform }} - run: | - # Drafts have no tag — `gh release view "v..."` returns the published - # release. Fetch the latest draft by ID via the API instead. - release_id=$(gh api "repos/${GITHUB_REPOSITORY}/releases" \ - --jq "[.[] | select(.draft and (.name | startswith(\"v${TO_TAG_VERSION}\")))] | sort_by(.created_at) | last | .id") - echo "Draft release id: $release_id" - # Prepend a marker that delete_draft_releases skips ("--editing--"), - # and rename the draft so each platform's smoke draft is preserved - # for review across matrix iterations. - body=$(gh api "repos/${GITHUB_REPOSITORY}/releases/${release_id}" --jq .body) - marked_body=$'--editing--\n[smoke '"$PLATFORM"$']\n\n'"$body" - gh api -X PATCH "repos/${GITHUB_REPOSITORY}/releases/${release_id}" \ - -f name="v${TO_TAG_VERSION} (smoke ${PLATFORM})" \ - -f body="$marked_body" \ - --jq '"Patched draft: \(.html_url)"' - echo "=== Draft release body (${PLATFORM}) ===" - echo "$body" - echo "=== end ===" From 31313d1764de987d4e8708dfa7b2a8c71a84908f Mon Sep 17 00:00:00 2001 From: jon8787 <112368577+jon8787@users.noreply.github.com> Date: Tue, 12 May 2026 16:49:17 +1000 Subject: [PATCH 8/8] UID2-6762: extract real package name from manifest, not github repo name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PyPI install snippet and Maven dependency block in release notes previously used `github.event.repository.name`, which differs from the actual published package name in 5 of 9 consumer repos: PyPI: uid2-client-python repo → uid2-client package Maven: uid2-attestation-azure → attestation-azure Maven: uid2-attestation-gcp → attestation-gcp Maven: uid2-attestation-aws → attestation-aws Maven: uid2-client-java → uid2-client Result: \`pip install\` / \`\` snippets shown on the GitHub Releases page produced 404s when copy-pasted. Fix: read the real package identifier from each manifest at release time. PyPI greps the top-level \`name = \"...\"\` from pyproject.toml; Maven uses \`mvn help:evaluate -Dexpression=project.artifactId\` as the canonical source. Both fail loudly if extraction returns empty. Fixes Behnam's review comment on PR #229. --- .../shared-publish-to-maven-versioned.yaml | 18 +++++++++++++++++- .../shared-publish-to-pypi-versioned.yaml | 17 ++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/.github/workflows/shared-publish-to-maven-versioned.yaml b/.github/workflows/shared-publish-to-maven-versioned.yaml index 06cefa6e..7888ae80 100644 --- a/.github/workflows/shared-publish-to-maven-versioned.yaml +++ b/.github/workflows/shared-publish-to-maven-versioned.yaml @@ -159,6 +159,22 @@ jobs: tag: v${{ steps.version.outputs.new_version }} github_token: ${{ inputs.merge_environment != '' && secrets.GH_MERGE_TOKEN || '' }} + - name: Extract Maven artifactId + id: package_name + run: | + # Maven artifactId comes from pom.xml, not the github repo name + # (e.g. uid2-attestation-azure repo publishes the `attestation-azure` + # artifact). Use `mvn help:evaluate` as the canonical source so + # release-notes install snippets match what `mvn deploy` actually + # published. + artifact_id=$(mvn -B -f "${{ inputs.working_dir }}/pom.xml" help:evaluate -Dexpression=project.artifactId -q -DforceStdout) + if [ -z "$artifact_id" ]; then + echo "ERROR: could not extract artifactId from ${{ inputs.working_dir }}/pom.xml" >&2 + exit 1 + fi + echo "Extracted Maven artifactId: $artifact_id" + echo "name=$artifact_id" >> "$GITHUB_OUTPUT" + - name: Create Release uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: @@ -166,4 +182,4 @@ jobs: new_version: ${{ steps.version.outputs.new_version }} github_token: ${{ secrets.GITHUB_TOKEN }} publish_platform: Maven - repo: ${{ env.REPO }} + repo: ${{ steps.package_name.outputs.name }} diff --git a/.github/workflows/shared-publish-to-pypi-versioned.yaml b/.github/workflows/shared-publish-to-pypi-versioned.yaml index b7fcc7c4..4aea7a84 100644 --- a/.github/workflows/shared-publish-to-pypi-versioned.yaml +++ b/.github/workflows/shared-publish-to-pypi-versioned.yaml @@ -97,6 +97,21 @@ jobs: tag: v${{ steps.version.outputs.new_version }} github_token: ${{ inputs.merge_environment != '' && secrets.GH_MERGE_TOKEN || '' }} + - name: Extract PyPI package name + id: package_name + run: | + # PyPI package name comes from pyproject.toml, not the github repo name + # (e.g. uid2-client-python repo publishes the `uid2-client` package). + # Read the top-level `name = "..."` field so release-notes install snippets + # match the real PyPI package, not the git repo. + name=$(grep -E '^\s*name\s*=' "${{ inputs.working_dir }}/pyproject.toml" | head -1 | cut -d '"' -f 2) + if [ -z "$name" ]; then + echo "ERROR: could not extract 'name' from ${{ inputs.working_dir }}/pyproject.toml" >&2 + exit 1 + fi + echo "Extracted PyPI package name: $name" + echo "name=$name" >> "$GITHUB_OUTPUT" + - name: Create Release uses: IABTechLab/uid2-shared-actions/actions/shared_create_releases@v3 with: @@ -104,4 +119,4 @@ jobs: new_version: ${{ steps.version.outputs.new_version }} github_token: ${{ secrets.GITHUB_TOKEN }} publish_platform: PyPI - repo: ${{ env.REPO }} + repo: ${{ steps.package_name.outputs.name }}