# Verify that Constellation builds are reproducible. # # The build-* jobs' matrix has three dimensions: a list of targets to build, a # list of runners to build on and a method of installing dependencies. The # produced binaries and OS images are expected to be bit-for-bit identical, # without any dependencies on the runtime setup details. # # The compare-* jobs only have the target dimension. They obtain the built # targets from all runners and check that there are no diffs between them. name: Reproducible Builds on: workflow_dispatch: schedule: - cron: "45 06 * * 1" # Every Monday at 6:45am pull_request: paths: - .github/workflows/reproducible-builds.yml 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-24.04" - "ubuntu-22.04" deps: - conventional - eccentric env: bazel_target: "//cli:${{ matrix.target }}" binary: "${{ matrix.target }}-${{ matrix.runner }}-${{ matrix.deps }}" runs-on: ${{ matrix.runner }} steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Setup dependencies uses: ./.github/actions/setup_bazel_nix if: matrix.deps == 'conventional' - name: Setup dependencies (eccentric) if: matrix.deps == 'eccentric' run: | version=$(cat .bazelversion) mkdir -p "$HOME/.local/bin" curl -fsSL -o "$HOME/.local/bin/bazel" "https://github.com/bazelbuild/bazel/releases/download/$version/bazel-$version-linux-x86_64" chmod a+x "$HOME/.local/bin/bazel" echo "$HOME/.local/bin" >> "$GITHUB_PATH" curl -fsSL -o "$HOME/.local/bin/nix-installer" https://github.com/DeterminateSystems/nix-installer/releases/download/v0.32.2/nix-installer-x86_64-linux # renovate:github-release chmod a+x "$HOME/.local/bin/nix-installer" "$HOME/.local/bin/nix-installer" install --no-confirm - 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@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: "binaries-${{ matrix.target }}-${{ matrix.runner }}-${{ matrix.deps }}" path: "${{ env.binary }}" - name: Upload hash artifact uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: "sha256sums-${{ matrix.target }}-${{ matrix.runner }}-${{ matrix.deps }}" path: "${{ env.binary }}.sha256" build-osimages: strategy: fail-fast: false matrix: target: - "azure_azure-sev-snp_stable" - "aws_aws-nitro-tpm_console" - "qemu_qemu-vtpm_debug" - "gcp_gcp-sev-snp_nightly" runner: ["ubuntu-24.04", "ubuntu-22.04"] env: bazel_target: "//image/system:${{ matrix.target }}" binary: "osimage-${{ matrix.target }}-${{ matrix.runner }}" runs-on: ${{ matrix.runner }} steps: - name: Remove security hardening features if: matrix.runner == 'ubuntu-24.04' shell: bash run: | # Taken from https://github.com/systemd/mkosi/blob/fcacc94b9f72d9b6b1f03779b0c6e07209ceb54b/action.yaml#L42-L57. sudo sysctl --ignore --write kernel.apparmor_restrict_unprivileged_unconfined=0 sudo sysctl --ignore --write kernel.apparmor_restrict_unprivileged_userns=0 # This command fails with a non-zero error code even though it unloads the apparmor profiles. # https://gitlab.com/apparmor/apparmor/-/issues/403 sudo aa-teardown || true sudo apt-get remove -y apparmor - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Setup bazel uses: ./.github/actions/setup_bazel_nix - name: Build shell: bash run: bazel build "${bazel_target}" - name: Copy shell: bash run: cp "$(bazel cquery --output=files "${bazel_target}")/constellation.raw" "${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@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: "osimages-${{ matrix.target }}-${{ matrix.runner }}" path: "${{ env.binary }}" - name: Upload hash artifact uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: "sha256sums-${{ matrix.target }}-${{ matrix.runner }}" path: "${{ env.binary }}.sha256" compare-binaries: 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-24.04 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Download binaries uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: pattern: "binaries-${{ matrix.target }}-*" merge-multiple: true - 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}" compare-osimages: needs: build-osimages strategy: fail-fast: false matrix: target: - "azure_azure-sev-snp_stable" - "aws_aws-nitro-tpm_console" - "qemu_qemu-vtpm_debug" - "gcp_gcp-sev-snp_nightly" runs-on: ubuntu-24.04 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Download os images uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: pattern: "osimages-${{ matrix.target }}-*" merge-multiple: true - name: Hash shell: bash if: runner.os == 'Linux' run: sha256sum osimage-* - name: Compare os images shell: bash run: | # shellcheck disable=SC2207,SC2116 list=($(echo "osimage-*")) diff -s --to-file="${list[0]}" "${list[@]:1}" | tee "${GITHUB_STEP_SUMMARY}"