From 4725fe812ab55075e24e4d44a3d6ee3f44bea2a5 Mon Sep 17 00:00:00 2001 From: "mkeeler@launchdarkly.com" Date: Tue, 31 Mar 2026 21:21:31 +0000 Subject: [PATCH 1/5] ci: use draft releases to support immutable GitHub releases --- .../manual-sdk-release-artifacts.yml | 72 ++-- .github/workflows/release-please.yml | 310 ++++++++++++------ release-please-config.json | 1 + 3 files changed, 242 insertions(+), 141 deletions(-) diff --git a/.github/workflows/manual-sdk-release-artifacts.yml b/.github/workflows/manual-sdk-release-artifacts.yml index a265bf2d5..7ca28cb80 100644 --- a/.github/workflows/manual-sdk-release-artifacts.yml +++ b/.github/workflows/manual-sdk-release-artifacts.yml @@ -40,10 +40,10 @@ jobs: # Each of the platforms for which release-artifacts need generated. os: [ ubuntu-22.04, windows-2022, macos-15-large ] runs-on: ${{ matrix.os }} - outputs: - hashes-linux: ${{ steps.release-sdk.outputs.hashes-linux }} - hashes-windows: ${{ steps.release-sdk.outputs.hashes-windows }} - hashes-macos: ${{ steps.release-sdk.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -58,12 +58,32 @@ jobs: github_token: ${{secrets.GITHUB_TOKEN}} sdk_path: ${{ needs.split-input.outputs.sdk_path}} sdk_cmake_target: ${{ needs.split-input.outputs.sdk_cmake_target}} + - name: Generate checksums file + env: + HASHES_LINUX: ${{ steps.release-sdk.outputs.hashes-linux }} + HASHES_WINDOWS: ${{ steps.release-sdk.outputs.hashes-windows }} + HASHES_MACOS: ${{ steps.release-sdk.outputs.hashes-macos }} + run: | + if [ -n "${HASHES_LINUX}" ]; then + echo "${HASHES_LINUX}" | base64 -d > checksums.txt + elif [ -n "${HASHES_WINDOWS}" ]; then + echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + elif [ -n "${HASHES_MACOS}" ]; then + echo "${HASHES_MACOS}" | base64 -d > checksums.txt + fi + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt release-sdk-mac-arm64: needs: split-input runs-on: macos-15 - outputs: - hashes-macos-arm64: ${{ steps.release-sdk.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -78,33 +98,13 @@ jobs: sdk_path: ${{ needs.split-input.outputs.sdk_path}} sdk_cmake_target: ${{ needs.split-input.outputs.sdk_cmake_target}} mac_artifact_arch: 'arm64' - - release-sdk-provenance: - needs: [ 'release-sdk' ] - strategy: - matrix: - # Generates a combined attestation for each platform - os: [ linux, windows, macos ] - permissions: - actions: read - id-token: write - contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-sdk.outputs[format('hashes-{0}', matrix.os)] }}" - upload-assets: true - upload-tag-name: ${{ inputs.tag }} - provenance-name: ${{ format('{0}-multiple-provenance.intoto.jsonl', matrix.os) }} - - release-sdk-mac-arm64-provenance: - needs: [ 'release-sdk-mac-arm64' ] - permissions: - actions: read - id-token: write - contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-sdk-mac-arm64.outputs.hashes-macos-arm64 }}" - upload-assets: true - upload-tag-name: ${{ inputs.tag }} - provenance-name: 'macos-arm64-multiple-provenance.intoto.jsonl' + - name: Generate checksums file + env: + HASHES: ${{ steps.release-sdk.outputs.hashes-macos }} + run: | + echo "${HASHES}" | base64 -d > checksums.txt + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index f6af1d0bb..5000c6d2e 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -26,18 +26,70 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} + create-tags: + needs: ['release-please'] + if: >- + needs.release-please.outputs.package-client-released == 'true' || + needs.release-please.outputs.package-server-released == 'true' || + needs.release-please.outputs.package-server-redis-released == 'true' || + needs.release-please.outputs.package-server-otel-released == 'true' + runs-on: ubuntu-22.04 + permissions: + contents: write + steps: + # https://github.com/actions/checkout/releases/tag/v4.3.0 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 + with: + fetch-depth: 0 + - name: Create release tags + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CLIENT_TAG: ${{ needs.release-please.outputs.package-client-tag }} + SERVER_TAG: ${{ needs.release-please.outputs.package-server-tag }} + SERVER_REDIS_TAG: ${{ needs.release-please.outputs.package-server-redis-tag }} + SERVER_OTEL_TAG: ${{ needs.release-please.outputs.package-server-otel-tag }} + CLIENT_RELEASED: ${{ needs.release-please.outputs.package-client-released }} + SERVER_RELEASED: ${{ needs.release-please.outputs.package-server-released }} + SERVER_REDIS_RELEASED: ${{ needs.release-please.outputs.package-server-redis-released }} + SERVER_OTEL_RELEASED: ${{ needs.release-please.outputs.package-server-otel-released }} + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + for pair in \ + "${CLIENT_RELEASED}:${CLIENT_TAG}" \ + "${SERVER_RELEASED}:${SERVER_TAG}" \ + "${SERVER_REDIS_RELEASED}:${SERVER_REDIS_TAG}" \ + "${SERVER_OTEL_RELEASED}:${SERVER_OTEL_TAG}"; do + + RELEASED="${pair%%:*}" + TAG="${pair#*:}" + + if [ "${RELEASED}" != "true" ] || [ -z "${TAG}" ]; then + continue + fi + + if gh api "repos/${{ github.repository }}/git/ref/tags/${TAG}" >/dev/null 2>&1; then + echo "Tag ${TAG} already exists, skipping creation." + else + echo "Creating tag ${TAG}." + git tag "${TAG}" + git push origin "${TAG}" + fi + done + release-client: strategy: matrix: # Each of the platforms for which release-artifacts need generated. os: [ ubuntu-22.04, windows-2022, macos-15-large ] runs-on: ${{ matrix.os }} - needs: [ 'release-please' ] + needs: [ 'release-please', 'create-tags' ] if: ${{ needs.release-please.outputs.package-client-released == 'true'}} - outputs: - hashes-linux: ${{ steps.release-client.outputs.hashes-linux }} - hashes-windows: ${{ steps.release-client.outputs.hashes-windows }} - hashes-macos: ${{ steps.release-client.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -50,13 +102,33 @@ jobs: github_token: ${{secrets.GITHUB_TOKEN}} sdk_path: 'libs/client-sdk' sdk_cmake_target: 'launchdarkly-cpp-client' + - name: Generate checksums file + env: + HASHES_LINUX: ${{ steps.release-client.outputs.hashes-linux }} + HASHES_WINDOWS: ${{ steps.release-client.outputs.hashes-windows }} + HASHES_MACOS: ${{ steps.release-client.outputs.hashes-macos }} + run: | + if [ -n "${HASHES_LINUX}" ]; then + echo "${HASHES_LINUX}" | base64 -d > checksums.txt + elif [ -n "${HASHES_WINDOWS}" ]; then + echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + elif [ -n "${HASHES_MACOS}" ]; then + echo "${HASHES_MACOS}" | base64 -d > checksums.txt + fi + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt release-client-mac-arm64: runs-on: macos-15 - needs: [ 'release-please' ] + needs: [ 'release-please', 'create-tags' ] if: ${{ needs.release-please.outputs.package-client-released == 'true'}} - outputs: - hashes-macos-arm64: ${{ steps.release-client.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -69,6 +141,16 @@ jobs: sdk_path: 'libs/client-sdk' sdk_cmake_target: 'launchdarkly-cpp-client' mac_artifact_arch: 'arm64' + - name: Generate checksums file + env: + HASHES: ${{ steps.release-client.outputs.hashes-macos }} + run: | + echo "${HASHES}" | base64 -d > checksums.txt + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt release-server: strategy: @@ -76,12 +158,12 @@ jobs: # Each of the platforms for which release-artifacts need generated. os: [ ubuntu-22.04, windows-2022, macos-15-large ] runs-on: ${{ matrix.os }} - needs: [ 'release-please' ] + needs: [ 'release-please', 'create-tags' ] if: ${{ needs.release-please.outputs.package-server-released == 'true'}} - outputs: - hashes-linux: ${{ steps.release-server.outputs.hashes-linux }} - hashes-windows: ${{ steps.release-server.outputs.hashes-windows }} - hashes-macos: ${{ steps.release-server.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -94,13 +176,33 @@ jobs: github_token: ${{secrets.GITHUB_TOKEN}} sdk_path: 'libs/server-sdk' sdk_cmake_target: 'launchdarkly-cpp-server' + - name: Generate checksums file + env: + HASHES_LINUX: ${{ steps.release-server.outputs.hashes-linux }} + HASHES_WINDOWS: ${{ steps.release-server.outputs.hashes-windows }} + HASHES_MACOS: ${{ steps.release-server.outputs.hashes-macos }} + run: | + if [ -n "${HASHES_LINUX}" ]; then + echo "${HASHES_LINUX}" | base64 -d > checksums.txt + elif [ -n "${HASHES_WINDOWS}" ]; then + echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + elif [ -n "${HASHES_MACOS}" ]; then + echo "${HASHES_MACOS}" | base64 -d > checksums.txt + fi + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt release-server-mac-arm64: runs-on: macos-15 - needs: [ 'release-please' ] + needs: [ 'release-please', 'create-tags' ] if: ${{ needs.release-please.outputs.package-server-released == 'true'}} - outputs: - hashes-macos-arm64: ${{ steps.release-server.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -113,6 +215,16 @@ jobs: sdk_path: 'libs/server-sdk' sdk_cmake_target: 'launchdarkly-cpp-server' mac_artifact_arch: 'arm64' + - name: Generate checksums file + env: + HASHES: ${{ steps.release-server.outputs.hashes-macos }} + run: | + echo "${HASHES}" | base64 -d > checksums.txt + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt release-server-redis: strategy: @@ -120,12 +232,12 @@ jobs: # Each of the platforms for which release-artifacts need generated. os: [ ubuntu-22.04, windows-2022, macos-15-large ] runs-on: ${{ matrix.os }} - needs: [ 'release-please' ] + needs: [ 'release-please', 'create-tags' ] if: ${{ needs.release-please.outputs.package-server-redis-released == 'true'}} - outputs: - hashes-linux: ${{ steps.release-server-redis.outputs.hashes-linux }} - hashes-windows: ${{ steps.release-server-redis.outputs.hashes-windows }} - hashes-macos: ${{ steps.release-server-redis.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -138,13 +250,33 @@ jobs: github_token: ${{secrets.GITHUB_TOKEN}} sdk_path: 'libs/server-sdk-redis-source' sdk_cmake_target: 'launchdarkly-cpp-server-redis-source' + - name: Generate checksums file + env: + HASHES_LINUX: ${{ steps.release-server-redis.outputs.hashes-linux }} + HASHES_WINDOWS: ${{ steps.release-server-redis.outputs.hashes-windows }} + HASHES_MACOS: ${{ steps.release-server-redis.outputs.hashes-macos }} + run: | + if [ -n "${HASHES_LINUX}" ]; then + echo "${HASHES_LINUX}" | base64 -d > checksums.txt + elif [ -n "${HASHES_WINDOWS}" ]; then + echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + elif [ -n "${HASHES_MACOS}" ]; then + echo "${HASHES_MACOS}" | base64 -d > checksums.txt + fi + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt release-server-redis-mac-arm64: runs-on: macos-15 - needs: [ 'release-please' ] + needs: [ 'release-please', 'create-tags' ] if: ${{ needs.release-please.outputs.package-server-redis-released == 'true'}} - outputs: - hashes-macos-arm64: ${{ steps.release-server-redis.outputs.hashes-macos }} + permissions: + contents: write + attestations: write + id-token: write steps: # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 @@ -157,93 +289,61 @@ jobs: sdk_path: 'libs/server-sdk-redis-source' sdk_cmake_target: 'launchdarkly-cpp-server-redis-source' mac_artifact_arch: 'arm64' + - name: Generate checksums file + env: + HASHES: ${{ steps.release-server-redis.outputs.hashes-macos }} + run: | + echo "${HASHES}" | base64 -d > checksums.txt + shell: bash + - name: Attest build provenance + uses: actions/attest@v4 + with: + subject-checksums: checksums.txt - release-client-provenance: - needs: [ 'release-please', 'release-client' ] - strategy: - matrix: - # Generates a combined attestation for each platform - os: [ linux, windows, macos ] - permissions: - actions: read - id-token: write - contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-client.outputs[format('hashes-{0}', matrix.os)] }}" - upload-assets: true - upload-tag-name: ${{ needs.release-please.outputs.package-client-tag }} - provenance-name: ${{ format('{0}-client-multiple-provenance.intoto.jsonl', matrix.os) }} - - release-client-mac-arm64-provenance: - needs: [ 'release-please', 'release-client-mac-arm64' ] - permissions: - actions: read - id-token: write - contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-client-mac-arm64.outputs.hashes-macos-arm64 }}" - upload-assets: true - upload-tag-name: ${{ needs.release-please.outputs.package-client-tag }} - provenance-name: 'macos-arm64-client-multiple-provenance.intoto.jsonl' - - release-server-provenance: - needs: [ 'release-please', 'release-server' ] - strategy: - matrix: - # Generates a combined attestation for each platform - os: [ linux, windows, macos ] - permissions: - actions: read - id-token: write - contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-server.outputs[format('hashes-{0}', matrix.os)] }}" - upload-assets: true - upload-tag-name: ${{ needs.release-please.outputs.package-server-tag }} - provenance-name: ${{ format('{0}-server-multiple-provenance.intoto.jsonl', matrix.os) }} - - release-server-mac-arm64-provenance: - needs: [ 'release-please', 'release-server-mac-arm64' ] + publish-release-client: + needs: ['release-please', 'release-client', 'release-client-mac-arm64'] + if: ${{ needs.release-please.outputs.package-client-released == 'true' }} + runs-on: ubuntu-latest permissions: - actions: read - id-token: write contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-server-mac-arm64.outputs.hashes-macos-arm64 }}" - upload-assets: true - upload-tag-name: ${{ needs.release-please.outputs.package-server-tag }} - provenance-name: 'macos-arm64-server-multiple-provenance.intoto.jsonl' + steps: + - name: Publish release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG_NAME: ${{ needs.release-please.outputs.package-client-tag }} + run: > + gh release edit "$TAG_NAME" + --repo ${{ github.repository }} + --draft=false - release-server-redis-provenance: - needs: [ 'release-please', 'release-server-redis' ] - strategy: - matrix: - # Generates a combined attestation for each platform - os: [ linux, windows, macos ] + publish-release-server: + needs: ['release-please', 'release-server', 'release-server-mac-arm64'] + if: ${{ needs.release-please.outputs.package-server-released == 'true' }} + runs-on: ubuntu-latest permissions: - actions: read - id-token: write contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-server-redis.outputs[format('hashes-{0}', matrix.os)] }}" - upload-assets: true - upload-tag-name: ${{ needs.release-please.outputs.package-server-redis-tag }} - provenance-name: ${{ format('{0}-server-redis-multiple-provenance.intoto.jsonl', matrix.os) }} + steps: + - name: Publish release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG_NAME: ${{ needs.release-please.outputs.package-server-tag }} + run: > + gh release edit "$TAG_NAME" + --repo ${{ github.repository }} + --draft=false - release-server-redis-mac-arm64-provenance: - needs: [ 'release-please', 'release-server-redis-mac-arm64' ] + publish-release-server-redis: + needs: ['release-please', 'release-server-redis', 'release-server-redis-mac-arm64'] + if: ${{ needs.release-please.outputs.package-server-redis-released == 'true' }} + runs-on: ubuntu-latest permissions: - actions: read - id-token: write contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.release-server-redis-mac-arm64.outputs.hashes-macos-arm64 }}" - upload-assets: true - upload-tag-name: ${{ needs.release-please.outputs.package-server-redis-tag }} - provenance-name: 'macos-arm64-server-redis-multiple-provenance.intoto.jsonl' + steps: + - name: Publish release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG_NAME: ${{ needs.release-please.outputs.package-server-redis-tag }} + run: > + gh release edit "$TAG_NAME" + --repo ${{ github.repository }} + --draft=false diff --git a/release-please-config.json b/release-please-config.json index 224c1644a..e76bbb8f6 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -2,6 +2,7 @@ "plugins": [ "node-workspace" ], + "draft": true, "packages": { "libs/client-sdk": { "extra-files": [ From 87b0e9dae6d72cf41a7dc0ad9a3ef69c4931a0f6 Mon Sep 17 00:00:00 2001 From: "mkeeler@launchdarkly.com" Date: Tue, 31 Mar 2026 21:42:45 +0000 Subject: [PATCH 2/5] ci: add force-tag-creation and publish_release option --- .../manual-sdk-release-artifacts.yml | 22 ++++++++++++++- release-please-config.json | 28 +++++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/.github/workflows/manual-sdk-release-artifacts.yml b/.github/workflows/manual-sdk-release-artifacts.yml index 7ca28cb80..9b30cc3b3 100644 --- a/.github/workflows/manual-sdk-release-artifacts.yml +++ b/.github/workflows/manual-sdk-release-artifacts.yml @@ -16,6 +16,11 @@ on: - libs/client-sdk:launchdarkly-cpp-client - libs/server-sdk:launchdarkly-cpp-server - libs/server-sdk-redis-source:launchdarkly-cpp-server-redis-source + publish_release: + description: 'Publish (un-draft) the release after all artifacts are uploaded?' + type: boolean + required: false + default: true name: Publish SDK Artifacts @@ -76,7 +81,6 @@ jobs: uses: actions/attest@v4 with: subject-checksums: checksums.txt - release-sdk-mac-arm64: needs: split-input runs-on: macos-15 @@ -108,3 +112,19 @@ jobs: uses: actions/attest@v4 with: subject-checksums: checksums.txt + + publish-release: + needs: ['release-sdk', 'release-sdk-mac-arm64'] + if: ${{ inputs.publish_release }} + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Publish release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG_NAME: ${{ inputs.tag }} + run: > + gh release edit "$TAG_NAME" + --repo ${{ github.repository }} + --draft=false diff --git a/release-please-config.json b/release-please-config.json index e76bbb8f6..0693cb538 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -10,7 +10,8 @@ "tests/client_c_bindings_test.cpp", "tests/client_test.cpp", "CMakeLists.txt" - ] + ], + "force-tag-creation": true }, "libs/server-sdk": { "extra-files": [ @@ -18,22 +19,33 @@ "tests/server_c_bindings_test.cpp", "tests/client_test.cpp", "CMakeLists.txt" - ] + ], + "force-tag-creation": true }, "libs/server-sdk-redis-source": { "extra-files": [ "CMakeLists.txt" - ] + ], + "force-tag-creation": true }, "libs/server-sdk-otel": { "bump-minor-pre-major": true, "extra-files": [ "CMakeLists.txt" - ] + ], + "force-tag-creation": true }, - "libs/server-sent-events": {}, - "libs/common": {}, - "libs/internal": {}, - "libs/networking": {} + "libs/server-sent-events": { + "force-tag-creation": true + }, + "libs/common": { + "force-tag-creation": true + }, + "libs/internal": { + "force-tag-creation": true + }, + "libs/networking": { + "force-tag-creation": true + } } } From 54a703dea74e642901d7769186592721ea641c44 Mon Sep 17 00:00:00 2001 From: "mkeeler@launchdarkly.com" Date: Wed, 1 Apr 2026 23:05:43 +0000 Subject: [PATCH 3/5] ci: split release-please into independent release and PR creation steps --- .github/workflows/release-please.yml | 69 ++++++++++++++++------------ 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 5000c6d2e..2572510b3 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -20,38 +20,38 @@ jobs: package-server-otel-released: ${{ steps.release.outputs['libs/server-sdk-otel--release_created'] }} package-server-otel-tag: ${{ steps.release.outputs['libs/server-sdk-otel--tag_name'] }} steps: - # https://github.com/googleapis/release-please-action/releases/tag/v4.3.0 - - uses: googleapis/release-please-action@c2a5a2bd6a758a0937f1ddb1e8950609867ed15c + # Create any releases first, then create tags, and then optionally create any new PRs. + - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 id: release with: token: ${{ secrets.GITHUB_TOKEN }} + skip-github-pull-request: true - create-tags: - needs: ['release-please'] - if: >- - needs.release-please.outputs.package-client-released == 'true' || - needs.release-please.outputs.package-server-released == 'true' || - needs.release-please.outputs.package-server-redis-released == 'true' || - needs.release-please.outputs.package-server-otel-released == 'true' - runs-on: ubuntu-22.04 - permissions: - contents: write - steps: + # Need the repository content to be able to create and push tags. # https://github.com/actions/checkout/releases/tag/v4.3.0 - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 - with: - fetch-depth: 0 + if: >- + steps.release.outputs['libs/client-sdk--release_created'] == 'true' || + steps.release.outputs['libs/server-sdk--release_created'] == 'true' || + steps.release.outputs['libs/server-sdk-redis-source--release_created'] == 'true' || + steps.release.outputs['libs/server-sdk-otel--release_created'] == 'true' + - name: Create release tags + if: >- + steps.release.outputs['libs/client-sdk--release_created'] == 'true' || + steps.release.outputs['libs/server-sdk--release_created'] == 'true' || + steps.release.outputs['libs/server-sdk-redis-source--release_created'] == 'true' || + steps.release.outputs['libs/server-sdk-otel--release_created'] == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CLIENT_TAG: ${{ needs.release-please.outputs.package-client-tag }} - SERVER_TAG: ${{ needs.release-please.outputs.package-server-tag }} - SERVER_REDIS_TAG: ${{ needs.release-please.outputs.package-server-redis-tag }} - SERVER_OTEL_TAG: ${{ needs.release-please.outputs.package-server-otel-tag }} - CLIENT_RELEASED: ${{ needs.release-please.outputs.package-client-released }} - SERVER_RELEASED: ${{ needs.release-please.outputs.package-server-released }} - SERVER_REDIS_RELEASED: ${{ needs.release-please.outputs.package-server-redis-released }} - SERVER_OTEL_RELEASED: ${{ needs.release-please.outputs.package-server-otel-released }} + CLIENT_TAG: ${{ steps.release.outputs['libs/client-sdk--tag_name'] }} + SERVER_TAG: ${{ steps.release.outputs['libs/server-sdk--tag_name'] }} + SERVER_REDIS_TAG: ${{ steps.release.outputs['libs/server-sdk-redis-source--tag_name'] }} + SERVER_OTEL_TAG: ${{ steps.release.outputs['libs/server-sdk-otel--tag_name'] }} + CLIENT_RELEASED: ${{ steps.release.outputs['libs/client-sdk--release_created'] }} + SERVER_RELEASED: ${{ steps.release.outputs['libs/server-sdk--release_created'] }} + SERVER_REDIS_RELEASED: ${{ steps.release.outputs['libs/server-sdk-redis-source--release_created'] }} + SERVER_OTEL_RELEASED: ${{ steps.release.outputs['libs/server-sdk-otel--release_created'] }} run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" @@ -78,13 +78,24 @@ jobs: fi done + - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 + if: >- + steps.release.outputs['libs/client-sdk--release_created'] != 'true' && + steps.release.outputs['libs/server-sdk--release_created'] != 'true' && + steps.release.outputs['libs/server-sdk-redis-source--release_created'] != 'true' && + steps.release.outputs['libs/server-sdk-otel--release_created'] != 'true' + id: release-prs + with: + token: ${{ secrets.GITHUB_TOKEN }} + skip-github-release: true + release-client: strategy: matrix: # Each of the platforms for which release-artifacts need generated. os: [ ubuntu-22.04, windows-2022, macos-15-large ] runs-on: ${{ matrix.os }} - needs: [ 'release-please', 'create-tags' ] + needs: [ 'release-please' ] if: ${{ needs.release-please.outputs.package-client-released == 'true'}} permissions: contents: write @@ -123,7 +134,7 @@ jobs: release-client-mac-arm64: runs-on: macos-15 - needs: [ 'release-please', 'create-tags' ] + needs: [ 'release-please' ] if: ${{ needs.release-please.outputs.package-client-released == 'true'}} permissions: contents: write @@ -158,7 +169,7 @@ jobs: # Each of the platforms for which release-artifacts need generated. os: [ ubuntu-22.04, windows-2022, macos-15-large ] runs-on: ${{ matrix.os }} - needs: [ 'release-please', 'create-tags' ] + needs: [ 'release-please' ] if: ${{ needs.release-please.outputs.package-server-released == 'true'}} permissions: contents: write @@ -197,7 +208,7 @@ jobs: release-server-mac-arm64: runs-on: macos-15 - needs: [ 'release-please', 'create-tags' ] + needs: [ 'release-please' ] if: ${{ needs.release-please.outputs.package-server-released == 'true'}} permissions: contents: write @@ -232,7 +243,7 @@ jobs: # Each of the platforms for which release-artifacts need generated. os: [ ubuntu-22.04, windows-2022, macos-15-large ] runs-on: ${{ matrix.os }} - needs: [ 'release-please', 'create-tags' ] + needs: [ 'release-please' ] if: ${{ needs.release-please.outputs.package-server-redis-released == 'true'}} permissions: contents: write @@ -271,7 +282,7 @@ jobs: release-server-redis-mac-arm64: runs-on: macos-15 - needs: [ 'release-please', 'create-tags' ] + needs: [ 'release-please' ] if: ${{ needs.release-please.outputs.package-server-redis-released == 'true'}} permissions: contents: write From 9b6cfae68f189d7aff7f7c730e1eb729163b4fdd Mon Sep 17 00:00:00 2001 From: "mkeeler@launchdarkly.com" Date: Thu, 2 Apr 2026 16:42:50 +0000 Subject: [PATCH 4/5] ci: fix publish_release boolean/string condition using format() --- .github/workflows/manual-sdk-release-artifacts.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manual-sdk-release-artifacts.yml b/.github/workflows/manual-sdk-release-artifacts.yml index 9b30cc3b3..99e14fd67 100644 --- a/.github/workflows/manual-sdk-release-artifacts.yml +++ b/.github/workflows/manual-sdk-release-artifacts.yml @@ -115,7 +115,7 @@ jobs: publish-release: needs: ['release-sdk', 'release-sdk-mac-arm64'] - if: ${{ inputs.publish_release }} + if: ${{ format('{0}', inputs.publish_release) == 'true' }} runs-on: ubuntu-latest permissions: contents: write From 2e858503661361877e7f85428cd1e553d1cec981 Mon Sep 17 00:00:00 2001 From: "mkeeler@launchdarkly.com" Date: Thu, 2 Apr 2026 22:05:04 +0000 Subject: [PATCH 5/5] ci: fix base64 decode for macOS BSD compatibility (-D instead of -d) --- .../manual-sdk-release-artifacts.yml | 11 ++++--- .github/workflows/release-please.yml | 33 ++++++++++++------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/.github/workflows/manual-sdk-release-artifacts.yml b/.github/workflows/manual-sdk-release-artifacts.yml index 99e14fd67..77bb7dae6 100644 --- a/.github/workflows/manual-sdk-release-artifacts.yml +++ b/.github/workflows/manual-sdk-release-artifacts.yml @@ -69,12 +69,14 @@ jobs: HASHES_WINDOWS: ${{ steps.release-sdk.outputs.hashes-windows }} HASHES_MACOS: ${{ steps.release-sdk.outputs.hashes-macos }} run: | + # BSD base64 (macOS) uses -D to decode; GNU base64 (Linux/Windows) uses -d. + if [[ "$OSTYPE" == darwin* ]]; then B64_DECODE="base64 -D"; else B64_DECODE="base64 -d"; fi if [ -n "${HASHES_LINUX}" ]; then - echo "${HASHES_LINUX}" | base64 -d > checksums.txt + echo "${HASHES_LINUX}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_WINDOWS}" ]; then - echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + echo "${HASHES_WINDOWS}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_MACOS}" ]; then - echo "${HASHES_MACOS}" | base64 -d > checksums.txt + echo "${HASHES_MACOS}" | $B64_DECODE > checksums.txt fi shell: bash - name: Attest build provenance @@ -106,7 +108,8 @@ jobs: env: HASHES: ${{ steps.release-sdk.outputs.hashes-macos }} run: | - echo "${HASHES}" | base64 -d > checksums.txt + # This job always runs on macOS, so use -D (BSD base64 decode). + echo "${HASHES}" | base64 -D > checksums.txt shell: bash - name: Attest build provenance uses: actions/attest@v4 diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 2572510b3..23083d608 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -119,12 +119,14 @@ jobs: HASHES_WINDOWS: ${{ steps.release-client.outputs.hashes-windows }} HASHES_MACOS: ${{ steps.release-client.outputs.hashes-macos }} run: | + # BSD base64 (macOS) uses -D to decode; GNU base64 (Linux/Windows) uses -d. + if [[ "$OSTYPE" == darwin* ]]; then B64_DECODE="base64 -D"; else B64_DECODE="base64 -d"; fi if [ -n "${HASHES_LINUX}" ]; then - echo "${HASHES_LINUX}" | base64 -d > checksums.txt + echo "${HASHES_LINUX}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_WINDOWS}" ]; then - echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + echo "${HASHES_WINDOWS}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_MACOS}" ]; then - echo "${HASHES_MACOS}" | base64 -d > checksums.txt + echo "${HASHES_MACOS}" | $B64_DECODE > checksums.txt fi shell: bash - name: Attest build provenance @@ -156,7 +158,8 @@ jobs: env: HASHES: ${{ steps.release-client.outputs.hashes-macos }} run: | - echo "${HASHES}" | base64 -d > checksums.txt + # This job always runs on macOS, so use -D (BSD base64 decode). + echo "${HASHES}" | base64 -D > checksums.txt shell: bash - name: Attest build provenance uses: actions/attest@v4 @@ -193,12 +196,14 @@ jobs: HASHES_WINDOWS: ${{ steps.release-server.outputs.hashes-windows }} HASHES_MACOS: ${{ steps.release-server.outputs.hashes-macos }} run: | + # BSD base64 (macOS) uses -D to decode; GNU base64 (Linux/Windows) uses -d. + if [[ "$OSTYPE" == darwin* ]]; then B64_DECODE="base64 -D"; else B64_DECODE="base64 -d"; fi if [ -n "${HASHES_LINUX}" ]; then - echo "${HASHES_LINUX}" | base64 -d > checksums.txt + echo "${HASHES_LINUX}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_WINDOWS}" ]; then - echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + echo "${HASHES_WINDOWS}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_MACOS}" ]; then - echo "${HASHES_MACOS}" | base64 -d > checksums.txt + echo "${HASHES_MACOS}" | $B64_DECODE > checksums.txt fi shell: bash - name: Attest build provenance @@ -230,7 +235,8 @@ jobs: env: HASHES: ${{ steps.release-server.outputs.hashes-macos }} run: | - echo "${HASHES}" | base64 -d > checksums.txt + # This job always runs on macOS, so use -D (BSD base64 decode). + echo "${HASHES}" | base64 -D > checksums.txt shell: bash - name: Attest build provenance uses: actions/attest@v4 @@ -267,12 +273,14 @@ jobs: HASHES_WINDOWS: ${{ steps.release-server-redis.outputs.hashes-windows }} HASHES_MACOS: ${{ steps.release-server-redis.outputs.hashes-macos }} run: | + # BSD base64 (macOS) uses -D to decode; GNU base64 (Linux/Windows) uses -d. + if [[ "$OSTYPE" == darwin* ]]; then B64_DECODE="base64 -D"; else B64_DECODE="base64 -d"; fi if [ -n "${HASHES_LINUX}" ]; then - echo "${HASHES_LINUX}" | base64 -d > checksums.txt + echo "${HASHES_LINUX}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_WINDOWS}" ]; then - echo "${HASHES_WINDOWS}" | base64 -d > checksums.txt + echo "${HASHES_WINDOWS}" | $B64_DECODE > checksums.txt elif [ -n "${HASHES_MACOS}" ]; then - echo "${HASHES_MACOS}" | base64 -d > checksums.txt + echo "${HASHES_MACOS}" | $B64_DECODE > checksums.txt fi shell: bash - name: Attest build provenance @@ -304,7 +312,8 @@ jobs: env: HASHES: ${{ steps.release-server-redis.outputs.hashes-macos }} run: | - echo "${HASHES}" | base64 -d > checksums.txt + # This job always runs on macOS, so use -D (BSD base64 decode). + echo "${HASHES}" | base64 -D > checksums.txt shell: bash - name: Attest build provenance uses: actions/attest@v4