mirror of
https://github.com/hanzoai/visor.git
synced 2026-09-24 17:04:14 +00:00
Delete upstream workflows
This fork does not ship upstream's releases, and its hosted-runner jobs never start here. Claude-Session: https://claude.ai/code/session_01HuMDfgFssPUptYUzgZ6Cp8
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
# Enable version updates for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
# Look for GitHub Actions workflows in the `root` directory
|
||||
directory: "/"
|
||||
# Check the for updates once a week
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -1,144 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
/**
|
||||
* Auto-assigns maintainers from governance/maintainers.yaml and areas.yaml to
|
||||
* incoming Pull Requests by combining area specialization with a randomized roster fallback.
|
||||
*
|
||||
* This function is executed as a GitHub Action. It parses the active
|
||||
* maintainers roster, filters out the PR author and bots, and assigns up to
|
||||
* two reviewers: prioritizing one suggested domain expert (if available) and
|
||||
* randomly selecting fallback reviewer(s) from the remaining eligible roster
|
||||
* to encourage knowledge sharing.
|
||||
*
|
||||
* @param {{
|
||||
* github: !Object,
|
||||
* context: !Object,
|
||||
* core: !Object,
|
||||
* }} params - The injected actions/github-script objects.
|
||||
* github: An authenticated Octokit REST client.
|
||||
* context: The GitHub Actions workflow context and payload.
|
||||
* core: The GitHub Actions core toolkit for logging/errors.
|
||||
*/
|
||||
module.exports = async ({github, context, core}) => {
|
||||
const {owner, repo} = context.repo;
|
||||
const prNum = context.payload.pull_request.number;
|
||||
const pr = context.payload.pull_request;
|
||||
const author = pr.user.login;
|
||||
const authorLower = author.toLowerCase();
|
||||
|
||||
// Filter out automated PRs
|
||||
if (pr.user.type === 'Bot') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if already assigned
|
||||
if ((pr.requested_reviewers || []).length > 0 ||
|
||||
(pr.assignees || []).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Read active maintainers and areas from governance YAML files
|
||||
let maintainersData, areasData;
|
||||
try {
|
||||
const workspace = process.env.GITHUB_WORKSPACE || '.';
|
||||
maintainersData = yaml.load(
|
||||
fs.readFileSync(
|
||||
path.join(workspace, 'governance/maintainers.yaml'), 'utf8'));
|
||||
areasData = yaml.load(
|
||||
fs.readFileSync(
|
||||
path.join(workspace, 'governance/areas.yaml'), 'utf8'));
|
||||
} catch (error) {
|
||||
core.setFailed(`Could not load governance YAML files: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter for active maintainers and build area mapping
|
||||
const maintainersByArea = new Map();
|
||||
const eligibleApprovers = [];
|
||||
for (const m of maintainersData?.maintainers || []) {
|
||||
if (m.status === 'ACTIVE' && m.github && m.github.toLowerCase() !== authorLower) {
|
||||
eligibleApprovers.push(m.github);
|
||||
for (const area of (m.areas || [])) {
|
||||
if (!maintainersByArea.has(area)) {
|
||||
maintainersByArea.set(area, []);
|
||||
}
|
||||
maintainersByArea.get(area).push(m.github);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eligibleApprovers.length === 0) {
|
||||
core.setFailed('No eligible approvers available to assign.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Find all specialists for areas covering the changed files
|
||||
let eligibleAreaSpecialists = [];
|
||||
try {
|
||||
const changedFiles = await github.paginate(github.rest.pulls.listFiles, {
|
||||
owner,
|
||||
repo,
|
||||
pull_number: prNum,
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const filePaths = changedFiles.map(f => '/' + f.filename);
|
||||
const matchedAreas = (areasData?.areas || [])
|
||||
.filter(area => area.paths?.some(p => filePaths.some(f => f === p || f.startsWith(p + '/'))))
|
||||
.map(area => area.name);
|
||||
|
||||
eligibleAreaSpecialists = [
|
||||
...new Set(matchedAreas.flatMap(area => maintainersByArea.get(area) || [])
|
||||
.filter(login => eligibleApprovers.includes(login))),
|
||||
];
|
||||
} catch (error) {
|
||||
core.warning(
|
||||
`Notice: Could not match changed files to areas: ${error.message}`);
|
||||
}
|
||||
|
||||
const shuffle = (array) => {
|
||||
const arr = [...array];
|
||||
for (let i = arr.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[arr[i], arr[j]] = [arr[j], arr[i]];
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
const selectedReviewers = [];
|
||||
|
||||
// Prioritize 1 specialist from the matched areas
|
||||
if (eligibleAreaSpecialists.length > 0) {
|
||||
const specialistsToAssign = shuffle(eligibleAreaSpecialists).slice(0, 1);
|
||||
for (const specialist of specialistsToAssign) {
|
||||
selectedReviewers.push(specialist);
|
||||
console.log(`Selected area specialist: ${specialist}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Fill remaining slot(s) (up to 2 total reviewers) from general eligible roster
|
||||
const selectedReviewersLower = selectedReviewers.map(r => r.toLowerCase());
|
||||
const remainingEligible = eligibleApprovers.filter(
|
||||
login => !selectedReviewersLower.includes(login.toLowerCase()));
|
||||
if (remainingEligible.length > 0 && selectedReviewers.length < 2) {
|
||||
const needed = 2 - selectedReviewers.length;
|
||||
const fallbackToAssign = shuffle(remainingEligible).slice(0, needed);
|
||||
for (const reviewer of fallbackToAssign) {
|
||||
selectedReviewers.push(reviewer);
|
||||
console.log(`Selected fallback roster reviewer: ${reviewer}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply assignment
|
||||
try {
|
||||
await github.rest.pulls.requestReviewers(
|
||||
{owner, repo, pull_number: prNum, reviewers: selectedReviewers});
|
||||
console.log(`Successfully requested review from [${
|
||||
selectedReviewers.join(', ')}] for PR #${prNum}`);
|
||||
} catch (error) {
|
||||
core.setFailed(`Failed to apply assignment API calls: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
# This workflow is used to automatically assign PRs to maintainers.
|
||||
name: Auto Assign
|
||||
|
||||
"on":
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
assign:
|
||||
if: github.event.pull_request.draft == false && github.repository == 'google/gvisor'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install js-yaml
|
||||
|
||||
- name: PR Assigner Bot
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |-
|
||||
const autoAssign = require('./.github/workflows/auto_assign.js');
|
||||
await autoAssign({ github, context, core });
|
||||
@@ -1,35 +0,0 @@
|
||||
name: CI
|
||||
|
||||
"on":
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: bazel
|
||||
run: |
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
sudo -E apt update && sudo -E apt install -y make
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
mkdir -p bin
|
||||
make copy TARGETS=runsc DESTINATION=bin/
|
||||
|
||||
- name: Upload runsc
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: runsc
|
||||
path: bin/runsc
|
||||
@@ -1,48 +0,0 @@
|
||||
# This workflow closes and locks PRs opened by users that are banned from
|
||||
# contributing.
|
||||
name: Close Banned PRs
|
||||
|
||||
"on":
|
||||
# `pull_request_target` is needed because PRs from forks only get a
|
||||
# read-only token under `pull_request`. This workflow never checks out or
|
||||
# runs any PR content, and never interpolates it into an expression, so the
|
||||
# usual `pull_request_target` risks do not apply.
|
||||
pull_request_target: # zizmor: ignore[dangerous-triggers]
|
||||
types: [opened, reopened]
|
||||
|
||||
jobs:
|
||||
close:
|
||||
if: github.repository == 'google/gvisor'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write # comment / close the PR
|
||||
issues: write # lock the PR conversation
|
||||
steps:
|
||||
- name: Close and lock PR if its author is banned
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
# Whitespace-separated list of banned GitHub usernames.
|
||||
BANNED_USERS: 'Rajkaran-122'
|
||||
with:
|
||||
script: |-
|
||||
const banned = process.env.BANNED_USERS.split(/\s+/)
|
||||
.filter((user) => user !== '')
|
||||
.map((user) => user.toLowerCase());
|
||||
const author = context.payload.pull_request.user.login;
|
||||
if (!banned.includes(author.toLowerCase())) {
|
||||
core.info(`${author} is not banned; leaving PR open.`);
|
||||
return;
|
||||
}
|
||||
const pr = {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
};
|
||||
await github.rest.issues.createComment({
|
||||
...pr,
|
||||
body: 'This PR was closed automatically because its author is ' +
|
||||
'not allowed to contribute to this repository.',
|
||||
});
|
||||
await github.rest.issues.update({...pr, state: 'closed'});
|
||||
await github.rest.issues.lock({...pr, lock_reason: 'spam'});
|
||||
core.info(`Closed and locked PR #${pr.issue_number} from ${author}.`);
|
||||
@@ -1,77 +0,0 @@
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
"on":
|
||||
schedule:
|
||||
# Daily at 1:00.
|
||||
- cron: '0 1 * * *'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners
|
||||
# Consider using larger runners for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go', 'javascript', 'python', 'ruby' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
|
||||
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- if: ${{ matrix.language == 'go' }}
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
@@ -1,35 +0,0 @@
|
||||
name: "License header"
|
||||
|
||||
"on":
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
fileheader:
|
||||
name: fileheader
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch base branch
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
git fetch --no-tags origin \
|
||||
"+refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}"
|
||||
|
||||
- name: Check license headers
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
tools/check_license_headers.sh "origin/${BASE_REF}"
|
||||
@@ -1,70 +0,0 @@
|
||||
# This workflow generates the Go branch. Note that this does not test the Go
|
||||
# branch, as this is rolled into the main continuous integration pipeline. This
|
||||
# workflow simply generates and pushes the branch, as long as appropriate
|
||||
# permissions are available.
|
||||
name: "Go"
|
||||
"on":
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- "feature/**"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
statuses: write
|
||||
steps:
|
||||
- id: setup
|
||||
run: |
|
||||
if ! [[ -z "${{ secrets.GO_TOKEN }}" ]]; then
|
||||
echo has_token=true >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo has_token=false >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- run: |
|
||||
jq -nc '{"state": "pending", "context": "go tests"}' | \
|
||||
curl -sL -X POST -d @- \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"${{ github.event.pull_request.statuses_url }}"
|
||||
if: github.event_name == 'pull_request'
|
||||
- uses: actions/checkout@v5
|
||||
if: github.event_name == 'push' && steps.setup.outputs.has_token == 'true'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: '${{ secrets.GO_TOKEN }}'
|
||||
- uses: actions/checkout@v5
|
||||
if: github.event_name == 'pull_request' || steps.setup.outputs.has_token != 'true'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/[email protected]
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
- run: tools/go_branch.sh
|
||||
- run: git checkout go && git clean -xf . && go build ./...
|
||||
- if: github.event_name == 'push'
|
||||
run: |
|
||||
git remote add upstream "https://github.com/${{ github.repository }}"
|
||||
git push upstream go:go
|
||||
- if: ${{ success() && github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
jq -nc '{"state": "success", "context": "go tests"}' | \
|
||||
curl -sL -X POST -d @- \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"${{ github.event.pull_request.statuses_url }}"
|
||||
- if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
jq -nc '{"state": "failure", "context": "go tests"}' | \
|
||||
curl -sL -X POST -d @- \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"${{ github.event.pull_request.statuses_url }}"
|
||||
@@ -1,20 +0,0 @@
|
||||
# This workflow revives issues that are still referenced in the code, and may
|
||||
# have been accidentally closed.
|
||||
name: "Issue reviver"
|
||||
"on":
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
issue_reviver:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
if: github.repository == 'google/gvisor'
|
||||
- run: make run TARGETS="//tools/github" ARGS="-path=. revive"
|
||||
if: github.repository == 'google/gvisor'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
@@ -1,16 +0,0 @@
|
||||
# Labeler labels incoming pull requests.
|
||||
name: "Labeler"
|
||||
"on":
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read # read labeler config
|
||||
pull-requests: write # apply labels to the PR
|
||||
steps:
|
||||
- uses: actions/labeler@v6
|
||||
if: github.base_ref == null
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
@@ -1,215 +0,0 @@
|
||||
# This workflow mirrors an existing gVisor release to the GitHub Releases page.
|
||||
#
|
||||
# It does NOT build anything. The release itself is produced by the internal
|
||||
# Buildkite pipeline (see .buildkite/release.yaml), which builds both
|
||||
# architectures and uploads the artifacts to gs://gvisor/releases/. This
|
||||
# workflow waits for those artifacts to appear, verifies them against the
|
||||
# published sha512 digests, and attaches them to a GitHub Release created from
|
||||
# the tag pushed by tools/tag_release.sh.
|
||||
#
|
||||
# The GCS bucket and the apt repository remain the canonical distribution
|
||||
# channels; see g3doc/user_guide/install.md.
|
||||
name: "Release Mirror"
|
||||
|
||||
"on":
|
||||
push:
|
||||
tags:
|
||||
- 'release-[0-9]+.[0-9]+'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to publish (e.g. release-20260817.0)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
# Never cancel a partially-published release; queue instead.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ inputs.tag || github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
publish-release:
|
||||
name: Mirror release to GitHub
|
||||
runs-on: ubuntu-latest
|
||||
# The Buildkite release step allows 180 minutes plus retries, and this job
|
||||
# polls for its output, so allow generous headroom.
|
||||
timeout-minutes: 300
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Determine tag and version
|
||||
id: meta
|
||||
env:
|
||||
INPUT_TAG: ${{ inputs.tag }}
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG="${INPUT_TAG:-${REF_NAME}}"
|
||||
# Mirrors the validation in tools/tag_release.sh.
|
||||
if ! [[ "${TAG}" =~ ^release-20[0-9]{6}\.[0-9]+$ ]]; then
|
||||
echo "::error::Not a valid release tag: '${TAG}'"
|
||||
exit 1
|
||||
fi
|
||||
echo "tag=${TAG}" >>"${GITHUB_OUTPUT}"
|
||||
echo "version=${TAG#release-}" >>"${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
|
||||
with:
|
||||
# Full history and tags are required to compute the changelog range.
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Verify tag exists
|
||||
env:
|
||||
TAG: ${{ steps.meta.outputs.tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null || {
|
||||
echo "::error::Tag '${TAG}' does not exist in this repository."
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Wait for Buildkite artifacts in GCS
|
||||
env:
|
||||
VERSION: ${{ steps.meta.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source .github/workflows/release_mirror_lib.sh
|
||||
|
||||
declare -a urls=()
|
||||
for arch in "${ARCHS[@]}"; do
|
||||
for f in "${RAW_FILES[@]}"; do
|
||||
urls+=("$(raw_url "${VERSION}" "${arch}" "${f}")")
|
||||
urls+=("$(raw_url "${VERSION}" "${arch}" "${f}.sha512")")
|
||||
done
|
||||
done
|
||||
|
||||
# gcloud uploads the repo tree in an unspecified order, so wait for
|
||||
# every required object rather than using one of them as a proxy.
|
||||
readonly TIMEOUT_SECONDS=$((240 * 60))
|
||||
start="$(date +%s)"
|
||||
for url in "${urls[@]}"; do
|
||||
while true; do
|
||||
# HEAD only: the tarballs are large and this loop is hot.
|
||||
# `|| true` keeps a transient network failure from tripping -e;
|
||||
# curl still emits 000 in that case.
|
||||
status="$(curl -sS -o /dev/null -w '%{http_code}' -I "${url}" 2>/dev/null || true)"
|
||||
if [[ "${status:-000}" == "200" ]]; then
|
||||
echo "ready: ${url}"
|
||||
break
|
||||
fi
|
||||
elapsed=$(( $(date +%s) - start ))
|
||||
if (( elapsed >= TIMEOUT_SECONDS )); then
|
||||
echo "::error::Timed out after $((elapsed / 60))m waiting for ${url} (last status ${status})."
|
||||
exit 1
|
||||
fi
|
||||
echo "waiting for ${url} (status ${status}, elapsed $((elapsed / 60))m)"
|
||||
sleep 30
|
||||
done
|
||||
done
|
||||
|
||||
- name: Download and verify artifacts
|
||||
env:
|
||||
VERSION: ${{ steps.meta.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source .github/workflows/release_mirror_lib.sh
|
||||
|
||||
mkdir -p dist
|
||||
for arch in "${ARCHS[@]}"; do
|
||||
stage="$(mktemp -d)"
|
||||
for f in "${RAW_FILES[@]}"; do
|
||||
curl -fsSL --retry 5 --retry-delay 10 --retry-all-errors \
|
||||
"$(raw_url "${VERSION}" "${arch}" "${f}")" -o "${stage}/${f}"
|
||||
curl -fsSL --retry 5 --retry-delay 10 --retry-all-errors \
|
||||
"$(raw_url "${VERSION}" "${arch}" "${f}.sha512")" -o "${stage}/${f}.sha512"
|
||||
# The published digest records the bare basename, so verify
|
||||
# before renaming for the flat release-asset namespace.
|
||||
(cd "${stage}" && sha512sum -c "${f}.sha512")
|
||||
mv "${stage}/${f}" "dist/$(asset_name "${f}" "${arch}")"
|
||||
done
|
||||
rm -rf "${stage}"
|
||||
done
|
||||
|
||||
# Compute both manifests over the same file list so that neither
|
||||
# includes the other.
|
||||
(
|
||||
cd dist
|
||||
mapfile -t assets < <(find . -maxdepth 1 -type f -printf '%P\n' | sort)
|
||||
sha256sum -- "${assets[@]}" >SHA256SUMS
|
||||
sha512sum -- "${assets[@]}" >SHA512SUMS
|
||||
)
|
||||
ls -l dist
|
||||
|
||||
- name: Generate release notes
|
||||
id: notes
|
||||
env:
|
||||
TAG: ${{ steps.meta.outputs.tag }}
|
||||
VERSION: ${{ steps.meta.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
prev_tag="$(git describe --tags --abbrev=0 --match 'release-*' "${TAG}^" 2>/dev/null || true)"
|
||||
if [[ -z "${prev_tag}" ]]; then
|
||||
echo "::error::Could not determine the release tag preceding ${TAG}; refusing to publish empty notes."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
notes="${RUNNER_TEMP}/release_notes.md"
|
||||
{
|
||||
echo "## gVisor release ${VERSION}"
|
||||
echo
|
||||
echo "Binaries are also available from the apt repository and the release bucket;"
|
||||
echo "see [Installation](https://gvisor.dev/docs/user_guide/install/)."
|
||||
echo
|
||||
echo "### Changes since \`${prev_tag}\`"
|
||||
echo
|
||||
# Fenced: commit subjects are not written as Markdown and regularly
|
||||
# contain characters that would otherwise be interpreted.
|
||||
echo '```text'
|
||||
git log "${prev_tag}..${TAG}" --no-merges --pretty=format:'%s (%h)'
|
||||
echo
|
||||
echo '```'
|
||||
echo
|
||||
echo "**Full changelog**: https://github.com/${GITHUB_REPOSITORY}/compare/${prev_tag}...${TAG}"
|
||||
} >"${notes}"
|
||||
|
||||
echo "path=${notes}" >>"${GITHUB_OUTPUT}"
|
||||
cat "${notes}"
|
||||
|
||||
- name: Create or update the GitHub release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
TAG: ${{ steps.meta.outputs.tag }}
|
||||
VERSION: ${{ steps.meta.outputs.version }}
|
||||
NOTES: ${{ steps.notes.outputs.path }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Only mark the newest release tag as "latest", so that backfilling an
|
||||
# older tag by hand does not move the pointer backwards.
|
||||
newest="$(git for-each-ref --count=1 --sort=-v:refname \
|
||||
--format='%(refname:short)' 'refs/tags/release-*')"
|
||||
if [[ "${TAG}" == "${newest}" ]]; then is_latest=true; else is_latest=false; fi
|
||||
|
||||
# The Buildkite release step retries automatically, so this has to be
|
||||
# safe to run more than once for the same tag.
|
||||
if gh release view "${TAG}" >/dev/null 2>&1; then
|
||||
echo "Release ${TAG} already exists; updating."
|
||||
gh release upload "${TAG}" dist/* --clobber
|
||||
gh release edit "${TAG}" \
|
||||
--title "gVisor ${VERSION}" \
|
||||
--notes-file "${NOTES}" \
|
||||
--latest="${is_latest}"
|
||||
else
|
||||
# --verify-tag: without it, a mistyped workflow_dispatch input would
|
||||
# create a bogus tag at the default branch head.
|
||||
gh release create "${TAG}" \
|
||||
--verify-tag \
|
||||
--title "gVisor ${VERSION}" \
|
||||
--notes-file "${NOTES}" \
|
||||
--latest="${is_latest}" \
|
||||
dist/*
|
||||
fi
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/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.
|
||||
|
||||
# Shared release-artifact layout for .github/workflows/release_mirror.yml.
|
||||
# Sourced, not executed; keeps the "wait" and "download" steps in agreement
|
||||
# about exactly which objects make up a release.
|
||||
|
||||
declare -r RELEASES_URL="https://storage.googleapis.com/gvisor/releases"
|
||||
|
||||
# Architecture directory names for raw artifacts. These are derived by
|
||||
# tools/make_release.sh from `file` output, and are also what
|
||||
# g3doc/user_guide/install.md tells users to plug in from `uname -m`.
|
||||
declare -ra ARCHS=(x86_64 aarch64)
|
||||
|
||||
# Raw artifacts to mirror, each with a sibling .sha512.
|
||||
#
|
||||
# Only the release tarball is mirrored. It already contains runsc,
|
||||
# runsc-metric-server and containerd-shim-runsc-v1, and those standalone
|
||||
# binaries are being retired. Debian packages are deliberately not mirrored
|
||||
# either: they are served by the apt repository, which also provides the
|
||||
# signed release metadata and the upgrade path that a release asset cannot.
|
||||
declare -ra RAW_FILES=(
|
||||
gvisor.tar.bz2
|
||||
gvisor.tar.zstd
|
||||
)
|
||||
|
||||
# raw_url <version> <arch> <filename>
|
||||
raw_url() {
|
||||
echo "${RELEASES_URL}/release/$1/$2/$3"
|
||||
}
|
||||
|
||||
# asset_name <filename> <arch>
|
||||
#
|
||||
# GitHub release assets share one flat namespace, so per-architecture files
|
||||
# have to carry the architecture in their name.
|
||||
asset_name() {
|
||||
case "$1" in
|
||||
*.tar.bz2) echo "${1%.tar.bz2}-$2.tar.bz2" ;;
|
||||
*.tar.zstd) echo "${1%.tar.zstd}-$2.tar.zstd" ;;
|
||||
*) echo "$1-$2" ;;
|
||||
esac
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
name: Mark stale issues and pull requests
|
||||
|
||||
# Please refer to https://github.com/actions/stale/blob/master/action.yml
|
||||
# to see all config knobs of the stale action.
|
||||
|
||||
"on":
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write # label / comment / close stale issues
|
||||
pull-requests: write # label / comment / close stale PRs
|
||||
steps:
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'A friendly reminder that this issue had no activity for 120 days.'
|
||||
stale-pr-message: 'A friendly reminder that this PR had no activity for 120 days.'
|
||||
stale-issue-label: 'stale-issue'
|
||||
stale-pr-label: 'stale-pr'
|
||||
days-before-stale: 120
|
||||
days-before-close: 90
|
||||
remove-stale-when-updated: true
|
||||
exempt-pr-labels: 'no-auto-close'
|
||||
exempt-issue-labels: 'no-auto-close,revived,type: enhancement,good first issue,status: help wanted,type: proposal'
|
||||
operations-per-run: 1000
|
||||
close-issue-label: 'auto-closed'
|
||||
close-pr-label: 'auto-closed'
|
||||
close-issue-message: 'This issue has been closed due to lack of activity.'
|
||||
close-pr-message: 'This PR has been closed due to lack of activity.'
|
||||
Reference in New Issue
Block a user