From 1778a26c46436c3f9444e8a9ae71868cb5a9742e Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 10:51:09 +0100 Subject: [PATCH] build: generate artifact attestions for released assets (#49781) * build: generate artifact attestions for released assets (#48239) * build: generate artifact attestions for released assets * chore: address review feedback --------- Co-authored-by: John Kleinschmidt (cherry picked from commit dec7f937ae20ac926e2c3ff51d5d01f99b5e3ea5) Co-authored-by: Samuel Attard * build: fixup attestation for release assets (#49732) * build: fixup attestation for release assets * Generate artifact attestation for generated artifacts * set id-token for attestation * Add artifact-metadata permission for attestation * add permissions for testing attestations * Revert "add permissions for testing attestations" This reverts commit 0284bed17511521d21fe8e0dd1bceab50545b1e2. * Revert "set id-token for attestation" This reverts commit 69a1b13a188418b13fc65dac28d33234acdaa1d7. * Revert "Generate artifact attestation for generated artifacts" This reverts commit ee0536eceb9eeeb94ee8105ffda66cbabd5751de. (cherry picked from commit 08528939102c3ec953b07207649ceeab64710fea) Co-authored-by: John Kleinschmidt * chore: update publish workflow Co-authored-by: John Kleinschmidt --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Samuel Attard Co-authored-by: John Kleinschmidt Co-authored-by: John Kleinschmidt --- .github/actions/build-electron/action.yml | 6 + .github/workflows/linux-publish.yml | 15 +- .github/workflows/macos-publish.yml | 20 +- .github/workflows/pipeline-electron-lint.yml | 6 +- .../pipeline-segment-electron-publish.yml | 237 ++++++++++++++++++ .github/workflows/windows-publish.yml | 15 +- package.json | 7 +- script/copy-pipeline-segment-publish.js | 32 +++ script/release/uploaders/upload.py | 8 + yarn.lock | 10 + 10 files changed, 344 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/pipeline-segment-electron-publish.yml create mode 100644 script/copy-pipeline-segment-publish.js diff --git a/.github/actions/build-electron/action.yml b/.github/actions/build-electron/action.yml index 2e8bec0953..fd115cb592 100644 --- a/.github/actions/build-electron/action.yml +++ b/.github/actions/build-electron/action.yml @@ -180,6 +180,7 @@ runs: - name: Publish Electron Dist ${{ inputs.step-suffix }} if: ${{ inputs.is-release == 'true' }} shell: bash + id: github-upload run: | rm -rf src/out/Default/obj cd src/electron @@ -190,6 +191,11 @@ runs: echo 'Uploading Electron release distribution to GitHub releases' script/release/uploaders/upload.py --verbose fi + - name: Generate artifact attestation + if: ${{ inputs.is-release == 'true' }} + uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0 + with: + subject-path: ${{ steps.github-upload.outputs.UPLOADED_PATHS }} - name: Generate siso report if: ${{ inputs.target-platform != 'win' && !cancelled() }} shell: bash diff --git a/.github/workflows/linux-publish.yml b/.github/workflows/linux-publish.yml index 98c08f31c9..2e3d71b32d 100644 --- a/.github/workflows/linux-publish.yml +++ b/.github/workflows/linux-publish.yml @@ -43,9 +43,12 @@ jobs: uses: ./src/electron/.github/actions/checkout publish-x64: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-linux with: environment: production-release @@ -60,9 +63,12 @@ jobs: secrets: inherit publish-arm: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-linux with: environment: production-release @@ -77,9 +83,12 @@ jobs: secrets: inherit publish-arm64: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-linux with: environment: production-release diff --git a/.github/workflows/macos-publish.yml b/.github/workflows/macos-publish.yml index b2f706af3b..3545351ae7 100644 --- a/.github/workflows/macos-publish.yml +++ b/.github/workflows/macos-publish.yml @@ -47,9 +47,12 @@ jobs: target-platform: macos publish-x64-darwin: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-macos with: environment: production-release @@ -64,9 +67,12 @@ jobs: secrets: inherit publish-x64-mas: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-macos with: environment: production-release @@ -81,9 +87,12 @@ jobs: secrets: inherit publish-arm64-darwin: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-macos with: environment: production-release @@ -98,9 +107,12 @@ jobs: secrets: inherit publish-arm64-mas: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-macos with: environment: production-release diff --git a/.github/workflows/pipeline-electron-lint.yml b/.github/workflows/pipeline-electron-lint.yml index f33ca6fc01..9785735625 100644 --- a/.github/workflows/pipeline-electron-lint.yml +++ b/.github/workflows/pipeline-electron-lint.yml @@ -85,4 +85,8 @@ jobs: run: | cd src/electron node script/yarn.js tsc -p tsconfig.script.json - + - name: Check GHA Workflows + shell: bash + run: | + cd src/electron + node script/copy-pipeline-segment-publish.js --check diff --git a/.github/workflows/pipeline-segment-electron-publish.yml b/.github/workflows/pipeline-segment-electron-publish.yml new file mode 100644 index 0000000000..329065b327 --- /dev/null +++ b/.github/workflows/pipeline-segment-electron-publish.yml @@ -0,0 +1,237 @@ +# AUTOGENERATED FILE - DO NOT EDIT MANUALLY +# ONLY EDIT .github/workflows/pipeline-segment-electron-build.yml + +name: Pipeline Segment - Electron Build +on: + workflow_call: + inputs: + environment: + description: using the production or testing environment + required: false + type: string + target-platform: + type: string + description: Platform to run on, can be macos, win or linux + required: true + target-arch: + type: string + description: Arch to build for, can be x64, arm64, ia32 or arm + required: true + target-variant: + type: string + description: Variant to build for, no effect on non-macOS target platforms. Can + be darwin, mas or all. + default: all + build-runs-on: + type: string + description: What host to run the build + required: true + build-container: + type: string + description: JSON container information for aks runs-on + required: false + default: '{"image":null}' + is-release: + description: Whether this build job is a release job + required: true + type: boolean + default: false + gn-build-type: + description: The gn build type - testing or release + required: true + type: string + default: testing + generate-symbols: + description: Whether or not to generate symbols + required: true + type: boolean + default: false + upload-to-storage: + description: Whether or not to upload build artifacts to external storage + required: true + type: string + default: "0" + is-asan: + description: Building the Address Sanitizer (ASan) Linux build + required: false + type: boolean + default: false + enable-ssh: + description: Enable SSH debugging + required: false + type: boolean + default: false +permissions: {} +concurrency: + group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch + }}-${{ inputs.target-variant }}-${{ inputs.is-asan }}-${{ + github.ref_protected == true && github.run_id || github.ref }} + cancel-in-progress: ${{ github.ref_protected != true }} +env: + CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }} + CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }} + DD_API_KEY: ${{ secrets.DD_API_KEY }} + ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }} + ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }} + SUDOWOODO_EXCHANGE_URL: ${{ secrets.SUDOWOODO_EXCHANGE_URL }} + SUDOWOODO_EXCHANGE_TOKEN: ${{ secrets.SUDOWOODO_EXCHANGE_TOKEN }} + GCLIENT_EXTRA_ARGS: ${{ inputs.target-platform == 'macos' && + '--custom-var=checkout_mac=True --custom-var=host_os=mac' || + inputs.target-platform == 'win' && '--custom-var=checkout_win=True' || + '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' }} + ELECTRON_OUT_DIR: Default + ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }} +jobs: + build: + defaults: + run: + shell: bash + runs-on: ${{ inputs.build-runs-on }} + permissions: + artifact-metadata: write + attestations: write + contents: read + id-token: write + container: ${{ fromJSON(inputs.build-container) }} + environment: ${{ inputs.environment }} + env: + TARGET_ARCH: ${{ inputs.target-arch }} + TARGET_PLATFORM: ${{ inputs.target-platform }} + steps: + - name: Create src dir + run: | + mkdir src + - name: Checkout Electron + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + path: src/electron + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + - name: Setup SSH Debugging + if: ${{ inputs.target-platform == 'macos' && (inputs.enable-ssh || + env.ACTIONS_STEP_DEBUG == 'true') }} + uses: ./src/electron/.github/actions/ssh-debug + with: + tunnel: "true" + env: + CLOUDFLARE_TUNNEL_CERT: ${{ secrets.CLOUDFLARE_TUNNEL_CERT }} + CLOUDFLARE_TUNNEL_HOSTNAME: ${{ vars.CLOUDFLARE_TUNNEL_HOSTNAME }} + CLOUDFLARE_USER_CA_CERT: ${{ secrets.CLOUDFLARE_USER_CA_CERT }} + AUTHORIZED_USERS: ${{ secrets.SSH_DEBUG_AUTHORIZED_USERS }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Free up space (macOS) + if: ${{ inputs.target-platform == 'macos' }} + uses: ./src/electron/.github/actions/free-space-macos + - name: Check disk space after freeing up space + if: ${{ inputs.target-platform == 'macos' }} + run: df -h + - name: Setup Node.js/npm + if: ${{ inputs.target-platform == 'macos' }} + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: 20.19.x + cache: yarn + cache-dependency-path: src/electron/yarn.lock + - name: Install Dependencies + uses: ./src/electron/.github/actions/install-dependencies + - name: Install AZCopy + if: ${{ inputs.target-platform == 'macos' }} + run: brew install azcopy + - name: Set GN_EXTRA_ARGS for Linux + if: ${{ inputs.target-platform == 'linux' }} + run: > + if [ "${{ inputs.target-arch }}" = "arm" ]; then + if [ "${{ inputs.is-release }}" = true ]; then + GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false symbol_level=1' + else + GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false' + fi + elif [ "${{ inputs.target-arch }}" = "arm64" ]; then + GN_EXTRA_ARGS='target_cpu="arm64" fatal_linker_warnings=false enable_linux_installer=false' + elif [ "${{ inputs.is-asan }}" = true ]; then + GN_EXTRA_ARGS='is_asan=true' + fi + + echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV + - name: Set Chromium Git Cookie + uses: ./src/electron/.github/actions/set-chromium-cookie + - name: Install Build Tools + uses: ./src/electron/.github/actions/install-build-tools + - name: Generate DEPS Hash + run: | + node src/electron/script/generate-deps-hash.js + DEPSHASH=v1-src-cache-$(cat src/electron/.depshash) + echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV + echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV + - name: Restore src cache via AZCopy + if: ${{ inputs.target-platform != 'linux' }} + uses: ./src/electron/.github/actions/restore-cache-azcopy + with: + target-platform: ${{ inputs.target-platform }} + - name: Restore src cache via AKS + if: ${{ inputs.target-platform == 'linux' }} + uses: ./src/electron/.github/actions/restore-cache-aks + - name: Checkout Electron + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + path: src/electron + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + - name: Fix Sync + if: ${{ inputs.target-platform != 'linux' }} + uses: ./src/electron/.github/actions/fix-sync + with: + target-platform: ${{ inputs.target-platform }} + env: + ELECTRON_DEPOT_TOOLS_DISABLE_LOG: true + - name: Init Build Tools + run: > + e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} + --import ${{ inputs.gn-build-type }} --target-cpu ${{ + inputs.target-arch }} --remote-build siso + - name: Run Electron Only Hooks + run: | + e d gclient runhooks --spec="solutions=[{'name':'src/electron','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':False},'managed':False}]" + - name: Regenerate DEPS Hash + run: > + (cd src/electron && git checkout .) && node + src/electron/script/generate-deps-hash.js + + echo "DEPSHASH=$(cat src/electron/.depshash)" >> $GITHUB_ENV + - name: Add CHROMIUM_BUILDTOOLS_PATH to env + run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV + - name: Free up space (macOS) + if: ${{ inputs.target-platform == 'macos' }} + uses: ./src/electron/.github/actions/free-space-macos + - name: Build Electron + if: ${{ inputs.target-platform != 'macos' || (inputs.target-variant == 'all' || + inputs.target-variant == 'darwin') }} + uses: ./src/electron/.github/actions/build-electron + with: + target-arch: ${{ inputs.target-arch }} + target-platform: ${{ inputs.target-platform }} + artifact-platform: ${{ inputs.target-platform == 'macos' && 'darwin' || + inputs.target-platform }} + is-release: ${{ inputs.is-release }} + generate-symbols: ${{ inputs.generate-symbols }} + upload-to-storage: ${{ inputs.upload-to-storage }} + is-asan: ${{ inputs.is-asan }} + - name: Set GN_EXTRA_ARGS for MAS Build + if: ${{ inputs.target-platform == 'macos' && (inputs.target-variant == 'all' || + inputs.target-variant == 'mas') }} + run: | + echo "MAS_BUILD=true" >> $GITHUB_ENV + GN_EXTRA_ARGS='is_mas_build=true' + echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV + - name: Build Electron (MAS) + if: ${{ inputs.target-platform == 'macos' && (inputs.target-variant == 'all' || + inputs.target-variant == 'mas') }} + uses: ./src/electron/.github/actions/build-electron + with: + target-arch: ${{ inputs.target-arch }} + target-platform: ${{ inputs.target-platform }} + artifact-platform: mas + is-release: ${{ inputs.is-release }} + generate-symbols: ${{ inputs.generate-symbols }} + upload-to-storage: ${{ inputs.upload-to-storage }} + step-suffix: (mas) diff --git a/.github/workflows/windows-publish.yml b/.github/workflows/windows-publish.yml index 0f6e9919bc..f3e7104df8 100644 --- a/.github/workflows/windows-publish.yml +++ b/.github/workflows/windows-publish.yml @@ -51,9 +51,12 @@ jobs: target-platform: win publish-x64-win: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-windows with: environment: production-release @@ -67,9 +70,12 @@ jobs: secrets: inherit publish-arm64-win: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-windows with: environment: production-release @@ -83,9 +89,12 @@ jobs: secrets: inherit publish-x86-win: - uses: ./.github/workflows/pipeline-segment-electron-build.yml + uses: ./.github/workflows/pipeline-segment-electron-publish.yml permissions: + artifact-metadata: write + attestations: write contents: read + id-token: write needs: checkout-windows with: environment: production-release diff --git a/package.json b/package.json index ef836b98b3..6130a53a52 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,8 @@ "url": "^0.11.4", "webpack": "^5.95.0", "webpack-cli": "^5.1.4", - "wrapper-webpack-plugin": "^2.2.0" + "wrapper-webpack-plugin": "^2.2.0", + "yaml": "^2.8.1" }, "private": true, "scripts": { @@ -132,6 +133,10 @@ "DEPS": [ "node script/gen-hunspell-filenames.js", "node script/gen-libc++-filenames.js" + ], + ".github/workflows/pipeline-segment-electron-build.yml": [ + "node script/copy-pipeline-segment-publish.js", + "git add .github/workflows/pipeline-segment-electron-publish.yml" ] }, "resolutions": { diff --git a/script/copy-pipeline-segment-publish.js b/script/copy-pipeline-segment-publish.js new file mode 100644 index 0000000000..e3690e1a56 --- /dev/null +++ b/script/copy-pipeline-segment-publish.js @@ -0,0 +1,32 @@ +const yaml = require('yaml'); + +const fs = require('node:fs'); +const path = require('node:path'); + +const PREFIX = '# AUTOGENERATED FILE - DO NOT EDIT MANUALLY\n# ONLY EDIT .github/workflows/pipeline-segment-electron-build.yml\n\n'; + +const base = path.resolve(__dirname, '../.github/workflows/pipeline-segment-electron-build.yml'); +const target = path.resolve(__dirname, '../.github/workflows/pipeline-segment-electron-publish.yml'); + +const baseContents = fs.readFileSync(base, 'utf-8'); + +const parsedBase = yaml.parse(baseContents); +parsedBase.jobs.build.permissions = { + 'artifact-metadata': 'write', + attestations: 'write', + contents: 'read', + 'id-token': 'write' +}; + +if (process.argv.includes('--check')) { + if (fs.readFileSync(target, 'utf-8') !== PREFIX + yaml.stringify(parsedBase)) { + console.error(`${target} is out of date`); + console.error('Please run "copy-pipeline-segment-publish.js" to update it'); + process.exit(1); + } +} else { + fs.writeFileSync( + target, + PREFIX + yaml.stringify(parsedBase) + ); +} diff --git a/script/release/uploaders/upload.py b/script/release/uploaders/upload.py index c5fa934b01..54a6518467 100755 --- a/script/release/uploaders/upload.py +++ b/script/release/uploaders/upload.py @@ -368,6 +368,14 @@ def upload_io_to_github(release, filename, filepath, version): sys.stdout.buffer.write(c) sys.stdout.flush() + if "GITHUB_OUTPUT" in os.environ: + output_path = os.environ["GITHUB_OUTPUT"] + with open(output_path, "r+", encoding='utf-8') as github_output: + if len(github_output.readlines()) > 0: + github_output.write(",") + else: + github_output.write('UPLOADED_PATHS=') + github_output.write(filepath) def upload_sha256_checksum(version, file_path, key_prefix=None): checksum_path = f'{file_path}.sha256sum' diff --git a/yarn.lock b/yarn.lock index ad60d396e9..62070f602d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -490,6 +490,7 @@ __metadata: webpack: "npm:^5.95.0" webpack-cli: "npm:^5.1.4" wrapper-webpack-plugin: "npm:^2.2.0" + yaml: "npm:^2.8.1" dependenciesMeta: abstract-socket: built: true @@ -14356,6 +14357,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.8.1": + version: 2.8.2 + resolution: "yaml@npm:2.8.2" + bin: + yaml: bin.mjs + checksum: 10c0/703e4dc1e34b324aa66876d63618dcacb9ed49f7e7fe9b70f1e703645be8d640f68ab84f12b86df8ac960bac37acf5513e115de7c970940617ce0343c8c9cd96 + languageName: node + linkType: hard + "yamux-js@npm:0.1.2": version: 0.1.2 resolution: "yamux-js@npm:0.1.2"