Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .buildkite/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,15 @@ steps:
label: ":ship: Release"
if: build.branch == "master" || build.tag != null
commands:
# Stamps the binaries below with release-<name>.
- ./.buildkite/scripts/release/tag.sh stage
- "make BAZEL_OPTIONS='--config=x86_64 --compilation_mode=opt' artifacts/x86_64"
- "make BAZEL_OPTIONS='--config=aarch64 --compilation_mode=opt' artifacts/aarch64"
- make artifacts-python
- make release RELEASE_NIGHTLY=$$RELEASE_NIGHTLY
- cd repo && gcloud storage cp --recursive . gs://gvisor/releases/
- (cd repo && gcloud storage cp --recursive . gs://gvisor/releases/)
# Pushes release-<name> to GitHub.
- ./.buildkite/scripts/release/tag.sh publish
agents:
queue: "release"
- <<: *common
Expand Down
88 changes: 88 additions & 0 deletions .buildkite/scripts/release/tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash

# Copyright 2026 The gVisor Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Makes the release tag appear on GitHub only after the artifacts are uploaded.
#
# stage adds release-<name> to the local checkout, before the build.
# publish pushes release-<name> to GitHub, after the upload.
#
# Both do nothing unless BUILDKITE_TAG is a staging tag.

set -euo pipefail

declare -r repo_url='https://github.com/google/gvisor.git'

# Holds the tag object between the two modes. Outside refs/tags, so it reaches
# neither `git describe` nor tools/make_release.sh.
declare -r staged_ref='refs/gvisor/staged-release-tag'

usage() {
echo "usage: $0 <stage|publish>" >&2
exit 1
}

if [[ "$#" -ne 1 ]]; then
usage
fi

declare -r staging_tag="${BUILDKITE_TAG:-}"
if [[ "${staging_tag}" != staging-release-* ]]; then
echo "Not a staged release build; nothing to do." >&2
exit 0
fi
declare -r tag="${staging_tag#staging-}"

# The object "${tag}" names in the remote; empty if it does not exist.
published_object() {
git ls-remote "${repo_url}" "refs/tags/${tag}" | head -n 1 | cut -f1
}

case "$1" in
stage)
git fetch --no-tags --force "${repo_url}" \
"refs/tags/${staging_tag}:${staged_ref}"
git tag -d "${staging_tag}" || true
if [[ "$(git rev-parse "${staged_ref}^{}")" != "$(git rev-parse HEAD)" ]]; then
echo "error: ${staging_tag} does not name the commit being built." >&2
exit 1
fi
git tag -f "${tag}" "${staged_ref}^{}"
# Fail now rather than after the build. The same object means a retry.
declare -r published="$(published_object)"
if [[ -n "${published}" && "${published}" != "$(git rev-parse "${staged_ref}")" ]]; then
echo "error: ${tag} already exists and names something else." >&2
exit 1
fi
;;

publish)
gh auth login --with-token <"${HOME}/.github-token"
gh auth setup-git
# Pushes the tag unless it is already published.
if [[ "$(published_object)" != "$(git rev-parse "${staged_ref}")" ]]; then
git push "${repo_url}" "${staged_ref}:refs/tags/${tag}"
fi
# Keeps `git describe` unambiguous on later builds.
if git ls-remote --exit-code "${repo_url}" \
"refs/tags/${staging_tag}" >/dev/null; then
git push --delete "${repo_url}" "refs/tags/${staging_tag}"
fi
;;

*)
usage
;;
esac
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ else
endif
.PHONY: staged-binaries-check

tag: ## Creates and pushes a release tag.
tag: ## Stages a release tag; the release pipeline publishes it once the artifacts are uploaded.
@tools/tag_release.sh "$(RELEASE_COMMIT)" "$(RELEASE_NAME)" "$(RELEASE_NOTES)"
.PHONY: tag

Expand Down
4 changes: 4 additions & 0 deletions tools/make_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ else
continue
fi
# LINT.ThenChange(../.buildkite/hooks/pre-command)
# A staging tag names a release that is still being built.
if [[ "$tag" == staging-release-* ]]; then
continue
fi
name=$(echo "${tag}" | cut -d'-' -f2)
base=$(echo "${name}" | cut -d'.' -f1)
# Install the "specific" release. This is the latest release with the
Expand Down
18 changes: 15 additions & 3 deletions tools/tag_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,19 @@ fi

# Tag the given commit (annotated, to record the committer). Note that the tag
# here is applied as a force, in case the tag already exists and is the same.
# The push will fail in this case (because it is not forced).
declare -r tag="release-${release}"
git tag -f -F "${message_file}" -a "${tag}" "${commit}" && \
git push origin tag "${tag}"
git tag -f -F "${message_file}" -a "${tag}" "${commit}"

# Push under a staging name; the release pipeline publishes the real tag once
# the artifacts are uploaded. A failed release leaves no tag behind.
git push --force origin "refs/tags/${tag}:refs/tags/staging-${tag}"
git tag -d "${tag}" # Not published yet.

set +x
cat <<EOF

Staged ${tag}. The release pipeline publishes it once the artifacts are in
gs://gvisor/releases/:

https://buildkite.com/gvisor/release/builds?branch=staging-${tag}
EOF
Loading