From 78fb0066e4cffcdcf25ffd5a8905013246bc8085 Mon Sep 17 00:00:00 2001 From: Malte Poll <1780588+malt3@users.noreply.github.com> Date: Fri, 23 Jun 2023 12:12:32 +0200 Subject: [PATCH] ci: add automated tests for reproducible builds (#1914) * ci: reproducible builds test * deps: upgrade actionlint to support macos-13 runners --- .github/actions/setup_bazel/action.yml | 23 +++++- .github/workflows/reproducible-builds.yml | 99 +++++++++++++++++++++++ bazel/toolchains/ci_deps.bzl | 24 +++--- 3 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/reproducible-builds.yml diff --git a/.github/actions/setup_bazel/action.yml b/.github/actions/setup_bazel/action.yml index 0c778b2ea..321ab857b 100644 --- a/.github/actions/setup_bazel/action.yml +++ b/.github/actions/setup_bazel/action.yml @@ -3,7 +3,7 @@ description: Setup Bazel for CI builds and tests inputs: useCache: - description: "Cache Bazel artifacts. Use 'true' to enable with rw, 'readonly' to download, and 'false' to disable." + description: "Cache Bazel artifacts. Use 'true' to enable with rw, 'readonly' to download, 'log' to disable cache but upload logs, and 'false' to disable." default: "false" required: true buildBuddyApiKey: @@ -17,11 +17,11 @@ runs: shell: bash run: | echo "::group::Check inputs" - if [[ "${{ inputs.useCache }}" != "true" && "${{ inputs.useCache }}" != "readonly" && "${{ inputs.useCache }}" != "false" ]]; then + if [[ "${{ inputs.useCache }}" != "true" && "${{ inputs.useCache }}" != "readonly" && "${{ inputs.useCache }}" != "logs" && "${{ inputs.useCache }}" != "false" ]]; then echo "Invalid value for 'useCache' input: '${{ inputs.useCache }}'. Must be 'true', 'readonly', or 'false'." exit 1 fi - if [[ "${{ inputs.useCache }}" == "true" || "${{ inputs.useCache }}" == "readonly" ]] && [[ -z "${{ inputs.buildBuddyApiKey }}" ]]; then + if [[ "${{ inputs.useCache }}" == "true" || "${{ inputs.useCache }}" == "readonly" || "${{ inputs.useCache }}" == "logs" ]] && [[ -z "${{ inputs.buildBuddyApiKey }}" ]]; then echo "BuildBuddy API key is required when cache is enabled." exit 1 fi @@ -69,6 +69,7 @@ runs: - name: Configure Bazel (readonly) shell: bash + if: inputs.useCache == 'readonly' env: WORKSPACE: ${{ github.workspace }} run: | @@ -76,6 +77,22 @@ runs: echo "build --remote_upload_local_results=false" >> "${WORKSPACE}/.bazeloverwriterc" echo "::endgroup::" + - name: Configure Bazel (logs) + shell: bash + if: inputs.useCache == 'logs' + env: + BUILDBUDDY_ORG_API_KEY: ${{ inputs.buildBuddyApiKey }} + WORKSPACE: ${{ github.workspace }} + run: | + echo "::group::Configure Bazel" + cat <> "${WORKSPACE}/.bazeloverwriterc" + build --bes_results_url=https://app.buildbuddy.io/invocation/ + build --bes_backend=grpcs://remote.buildbuddy.io + build --remote_header=x-buildbuddy-api-key=${BUILDBUDDY_ORG_API_KEY} + build --nolegacy_important_outputs + EOF + echo "::endgroup::" + - name: Disable disk cache on GitHub Actions runners shell: bash env: diff --git a/.github/workflows/reproducible-builds.yml b/.github/workflows/reproducible-builds.yml new file mode 100644 index 000000000..3d518e73e --- /dev/null +++ b/.github/workflows/reproducible-builds.yml @@ -0,0 +1,99 @@ +# Build Constellation CLI and check for reproducible builds +name: Reproducible Builds + +on: + workflow_dispatch: + schedule: + - cron: "45 06 * * 1" # Every Monday at 6:45am + +jobs: + build-binaries: + strategy: + fail-fast: false + matrix: + target: + - "cli_enterprise_darwin_amd64" + - "cli_enterprise_darwin_arm64" + - "cli_enterprise_linux_amd64" + - "cli_enterprise_linux_arm64" + - "cli_enterprise_windows_amd64" + runner: ["ubuntu-22.04", "macos-13"] + env: + bazel_target: "//cli:${{ matrix.target }}" + binary: "${{ matrix.target }}-${{ matrix.runner }}" + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} + + - name: Setup bazel + uses: ./.github/actions/setup_bazel + with: + useCache: "logs" + buildBuddyApiKey: ${{ secrets.BUILDBUDDY_ORG_API_KEY }} + + - name: Install current Bash on macOS + if: runner.os == 'macOS' + run: brew install bash + + - name: Build + shell: bash + run: bazel build "${bazel_target}" + + - name: Copy + shell: bash + run: cp "$(bazel cquery --output=files "${bazel_target}")" "${binary}" + + - name: Collect hash (linux) + shell: bash + if: runner.os == 'Linux' + run: sha256sum "${binary}" | tee "${binary}.sha256" + + - name: Collect hash (macOS) + shell: bash + if: runner.os == 'macOS' + run: shasum -a 256 "${binary}" | tee "${binary}.sha256" + + - name: Upload binary artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "binaries-${{ matrix.target }}" + path: "${{ env.binary }}" + + - name: Upload hash artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "sha256sums" + path: "${{ env.binary }}.sha256" + + compare: + needs: build-binaries + strategy: + fail-fast: false + matrix: + target: + - "cli_enterprise_darwin_amd64" + - "cli_enterprise_darwin_arm64" + - "cli_enterprise_linux_amd64" + - "cli_enterprise_linux_arm64" + - "cli_enterprise_windows_amd64" + runs-on: ubuntu-22.04 + steps: + - name: Download binaries + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: "binaries-${{ matrix.target }}" + + - name: Hash + shell: bash + if: runner.os == 'Linux' + run: sha256sum cli_enterprise* + + - name: Compare binaries + shell: bash + run: | + # shellcheck disable=SC2207,SC2116 + list=($(echo "cli_enterprise*")) + diff -s --to-file="${list[0]}" "${list[@]:1}" | tee "${GITHUB_STEP_SUMMARY}" diff --git a/bazel/toolchains/ci_deps.bzl b/bazel/toolchains/ci_deps.bzl index 6dcbf7799..b4bc48614 100644 --- a/bazel/toolchains/ci_deps.bzl +++ b/bazel/toolchains/ci_deps.bzl @@ -97,41 +97,41 @@ def _actionlint_deps(): name = "com_github_rhysd_actionlint_linux_amd64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/3c5818744143a5d6754edd3dcc4c2b32c9dfcdd3bb30e0e108fb5e5c505262d4", - "https://github.com/rhysd/actionlint/releases/download/v1.6.24/actionlint_1.6.24_linux_amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/80a54660e73ad55a0818372bdaa0dced82eb86f618e6bf1621e73f099e61c027", + "https://github.com/rhysd/actionlint/releases/download/v1.6.25/actionlint_1.6.25_linux_amd64.tar.gz", ], type = "tar.gz", - sha256 = "3c5818744143a5d6754edd3dcc4c2b32c9dfcdd3bb30e0e108fb5e5c505262d4", + sha256 = "80a54660e73ad55a0818372bdaa0dced82eb86f618e6bf1621e73f099e61c027", ) http_archive( name = "com_github_rhysd_actionlint_linux_arm64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/93cc9d1f4a01f0658423b41ecf3bd8c17c619003ec683be8bac9264d0361d0d8", - "https://github.com/rhysd/actionlint/releases/download/v1.6.24/actionlint_1.6.24_linux_arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/8bedeea8ed636891fd7351fa7ccbc75fdb5bee6efde5320162f712e8457e73ea", + "https://github.com/rhysd/actionlint/releases/download/v1.6.25/actionlint_1.6.25_linux_arm64.tar.gz", ], type = "tar.gz", - sha256 = "93cc9d1f4a01f0658423b41ecf3bd8c17c619003ec683be8bac9264d0361d0d8", + sha256 = "8bedeea8ed636891fd7351fa7ccbc75fdb5bee6efde5320162f712e8457e73ea", ) http_archive( name = "com_github_rhysd_actionlint_darwin_amd64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/ce9dd9653700e3ed00464dffddd3e2a61358cf96425f2f3dff840dfc1e105eab", - "https://github.com/rhysd/actionlint/releases/download/v1.6.24/actionlint_1.6.24_darwin_amd64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/30d69622ff9fbf564081515bf7d20538f2cb590150ef0c69fdcc56fa23fe85f1", + "https://github.com/rhysd/actionlint/releases/download/v1.6.25/actionlint_1.6.25_darwin_amd64.tar.gz", ], type = "tar.gz", - sha256 = "ce9dd9653700e3ed00464dffddd3e2a61358cf96425f2f3dff840dfc1e105eab", + sha256 = "30d69622ff9fbf564081515bf7d20538f2cb590150ef0c69fdcc56fa23fe85f1", ) http_archive( name = "com_github_rhysd_actionlint_darwin_arm64", build_file_content = """exports_files(["actionlint"], visibility = ["//visibility:public"])""", urls = [ - "https://cdn.confidential.cloud/constellation/cas/sha256/5477f8a5a4073ef086525a2512b2bf1201641cd544034ad0c66f329590638242", - "https://github.com/rhysd/actionlint/releases/download/v1.6.24/actionlint_1.6.24_darwin_arm64.tar.gz", + "https://cdn.confidential.cloud/constellation/cas/sha256/9153ebe7be2a33c9047e60aeb0d8d7b831b22fe99bbea63d365500c68245d6df", + "https://github.com/rhysd/actionlint/releases/download/v1.6.25/actionlint_1.6.25_darwin_arm64.tar.gz", ], type = "tar.gz", - sha256 = "5477f8a5a4073ef086525a2512b2bf1201641cd544034ad0c66f329590638242", + sha256 = "9153ebe7be2a33c9047e60aeb0d8d7b831b22fe99bbea63d365500c68245d6df", ) def _gofumpt_deps():