diff --git a/.bcr/source.template.json b/.bcr/source.template.json index ce4bbcce0f271..d25b0666ccef0 100644 --- a/.bcr/source.template.json +++ b/.bcr/source.template.json @@ -1,5 +1,5 @@ { "integrity": "**leave this alone**", "strip_prefix": "{REPO}-{VERSION}", - "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{VERSION}.zip" + "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{VERSION}.tar.gz" } diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000..99fc84c0663cc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# Configuration for 'git archive' +# see https://git-scm.com/docs/git-archive/2.40.0#ATTRIBUTES +# Don't include compatibility folder in the distribution artifact, just to reduce size +compatibility/ export-ignore \ No newline at end of file diff --git a/.github/workflows/publish_to_bcr.yaml b/.github/workflows/publish_to_bcr.yaml new file mode 100644 index 0000000000000..d20dc19e0b843 --- /dev/null +++ b/.github/workflows/publish_to_bcr.yaml @@ -0,0 +1,36 @@ +# Publish new releases to Bazel Central Registry. +name: Publish to BCR +on: + # Run the publish workflow after a successful release + # Will be triggered from the release.yaml workflow + workflow_call: + inputs: + tag_name: + required: true + type: string + secrets: + # This token should be owned by https://github.com/protobuf-team-bot + BCR_PUBLISH_TOKEN: + required: true + # In case of problems, let release engineers retry by manually dispatching + # the workflow from the GitHub UI + workflow_dispatch: + inputs: + tag_name: + description: git tag being released + required: true + type: string +jobs: + publish: + uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@v1.0.0 + with: + tag_name: ${{ inputs.tag_name }} + # GitHub repository which is a fork of the upstream where the Pull Request will be opened. + registry_fork: protocolbuffers/bazel-central-registry + permissions: + attestations: write + contents: write + id-token: write + secrets: + # Necessary to push to the BCR fork, and to open a pull request against a registry + publish_token: ${{ secrets.BCR_PUBLISH_TOKEN }} diff --git a/.github/workflows/release_bazel_module.yaml b/.github/workflows/release_bazel_module.yaml new file mode 100644 index 0000000000000..d073aff4f349c --- /dev/null +++ b/.github/workflows/release_bazel_module.yaml @@ -0,0 +1,33 @@ +# Prepare a release specifically for Bazel users, including a pre-built protoc. +name: Bazel Release +on: + # Can be triggered from the GitHub Actions ui, using the "Run workflow" button on + # https://github.com/protocolbuffers/protobuf/actions/workflows/release_bazel_module.yaml + # TODO(alexeagle): consider automating the trigger from a new release being created + workflow_dispatch: + inputs: + tag_name: + description: git tag that has the protoc release artifact + required: true + type: string +permissions: + id-token: write + attestations: write + contents: write +jobs: + release: + uses: bazel-contrib/.github/.github/workflows/release_ruleset.yaml@v7.2.3 + with: + release_files: protobuf-*.tar.gz + prerelease: false + tag_name: ${{ inputs.tag_name }} + # The release was already created by Google-internal mechanism, + # so there aren't any useful assertions to make here. + bazel_test_command: 'true' + publish: + needs: release + uses: ./.github/workflows/publish_to_bcr.yaml + with: + tag_name: ${{ inputs.tag_name }} + secrets: + BCR_PUBLISH_TOKEN: ${{ secrets.BCR_PUBLISH_TOKEN }} diff --git a/.github/workflows/release_prep.sh b/.github/workflows/release_prep.sh new file mode 100755 index 0000000000000..5f2ea54b1b125 --- /dev/null +++ b/.github/workflows/release_prep.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# NB: this file must be named release_prep.sh because the attestation generation doesn't trust user control. +# see https://github.com/bazel-contrib/.github/blob/v7.2.3/.github/workflows/release_ruleset.yaml#L33-L45 +set -o errexit -o nounset -o pipefail + +# Argument provided by reusable workflow caller, see +# https://github.com/bazel-contrib/.github/blob/v7.2.3/.github/workflows/release_ruleset.yaml#L104 +TAG=$1 +PREFIX="protobuf-${TAG:1}" +ARCHIVE="$PREFIX.tar.gz" +ARCHIVE_TMP=$(mktemp) +INTEGRITY_FILE=${PREFIX}/bazel/private/prebuilt_tool_integrity.bzl + +# NB: configuration for 'git archive' is in /.gitattributes +git archive --format=tar --prefix=${PREFIX}/ ${TAG} > $ARCHIVE_TMP +############ +# Patch up the archive to have integrity hashes for built binaries that we downloaded in the GHA workflow. +# Now that we've run `git archive` we are free to pollute the working directory. + +# Delete the placeholder file +tar --file $ARCHIVE_TMP --delete $INTEGRITY_FILE + +# Use jq to translate GitHub Releases json into a Starlark object +filter_releases=$(cat <<'EOF' +# Read the file assets already present on the release +reduce .assets[] as $a ( + # Start with an empty dictionary, and for each asset, add + {}; . + { + # The format required in starlark, i.e. "release-name": "deadbeef123" + ($a.name): ($a.digest | sub("^sha256:"; "")) + } +) +EOF +) + +mkdir -p ${PREFIX}/bazel/private +cat >${INTEGRITY_FILE} < $ARCHIVE +SHA=$(shasum -a 256 $ARCHIVE | awk '{print $1}') diff --git a/bazel/private/prebuilt_tool_integrity.bzl b/bazel/private/prebuilt_tool_integrity.bzl new file mode 100644 index 0000000000000..029aa8a033664 --- /dev/null +++ b/bazel/private/prebuilt_tool_integrity.bzl @@ -0,0 +1,20 @@ +"""Release binary integrity hashes. + +This file contents are entirely replaced during release publishing, by .github/workflows/release_prep.sh +so that the integrity of the prebuilt tools is included in the release artifact. + +The checked in content is only here to allow load() statements in the sources to resolve. +""" + +# Create a mapping for every tool name to the hash of /dev/null +NULLSHA = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +RELEASED_BINARY_INTEGRITY = { + "-".join([ + "protoc", + os, + arch, + ]): NULLSHA + for [os, arch] in { + "linux": ["aarch_64", "x86_64"], + } +}