Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add code freeze GitHub actions for releasing #56325

Merged
merged 6 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
51 changes: 51 additions & 0 deletions .github/workflows/code_freeze.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
on:
workflow_dispatch:
inputs:
type:
description: Enable/disable code freeze
required: true
type: choice
options:
- enable
- disable

secrets:
CODE_FREEZE_TOKEN:
required: true

name: Code Freeze

env:
NAPI_CLI_VERSION: 2.14.7
TURBO_VERSION: 1.10.9
NODE_MAINTENANCE_VERSION: 16
NODE_LTS_VERSION: 18

jobs:
start:
runs-on: ubuntu-latest
env:
NEXT_TELEMETRY_DISABLED: 1
# we build a dev binary for use in CI so skip downloading
# canary next-swc binaries in the monorepo
NEXT_SKIP_NATIVE_POSTINSTALL: 1
ijjk marked this conversation as resolved.
Show resolved Hide resolved

environment: release-${{ github.event.inputs.releaseType }}
steps:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 18
check-latest: true

- run: git clone https://github.com/vercel/next.js.git --depth=1 .

# https://github.com/actions/virtual-environments/issues/1187
- name: tune linux network
run: sudo ethtool -K eth0 tx off rx off

- run: corepack enable && pnpm --version
ijjk marked this conversation as resolved.
Show resolved Hide resolved
ijjk marked this conversation as resolved.
Show resolved Hide resolved

- run: node ./scripts/code-freeze.js --type ${{ github.event.inputs.type }}
env:
CODE_FREEZE_TOKEN: ${{ secrets.CODE_FREEZE_TOKEN }}
117 changes: 117 additions & 0 deletions scripts/code-freeze.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
const authToken = process.env.CODE_FREEZE_TOKEN

if (!authToken) {
throw new Error(`missing CODE_FREEZE_TOKEN env`)
}

const codeFreezeRule = {
context: 'Potentially publish release',
app_id: 15368,
}

async function updateRules(newRules) {
const res = await fetch(
`https://api.github.com/repos/vercel/next.js/branches/canary/protection`,
{
method: 'PUT',
headers: {
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${authToken}`,
'X-GitHub-Api-Version': '2022-11-28',
},
body: JSON.stringify(newRules),
}
)

if (!res.ok) {
throw new Error(
`Failed to check for rule ${res.status} ${await res.text()}`
)
}
}

async function getCurrentRules() {
const res = await fetch(
`https://api.github.com/repos/vercel/next.js/branches/canary/protection`,
{
headers: {
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${authToken}`,
'X-GitHub-Api-Version': '2022-11-28',
},
}
)

if (!res.ok) {
throw new Error(
`Failed to check for rule ${res.status} ${await res.text()}`
)
}
const data = await res.json()

return {
required_status_checks: {
strict: data.required_status_checks.strict,
// checks: data.required_status_checks.checks,
contexts: data.required_status_checks.contexts,
},
enforce_admins: data.enforce_admins.enabled,
required_pull_request_reviews: {
dismiss_stale_reviews:
data.required_pull_request_reviews.dismiss_stale_reviews,
require_code_owner_reviews:
data.required_pull_request_reviews.require_code_owner_reviews,
require_last_push_approval:
data.required_pull_request_reviews.require_last_push_approval,
required_approving_review_count:
data.required_pull_request_reviews.required_approving_review_count,
},
restrictions: data.restrictions || {
users: [],
teams: [],
apps: [],
},
}
}

async function main() {
const typeIdx = process.argv.indexOf('--type')
const type = process.argv[typeIdx + 1]

if (type !== 'enable' && type !== 'disable') {
throw new Error(`--type should be enable or disable`)
}
const isEnable = type === 'enable'
const currentRules = await getCurrentRules()
const hasRule = currentRules.required_status_checks.contexts?.some((ctx) => {
return ctx === codeFreezeRule.context
})

console.log(currentRules)

if (isEnable) {
if (hasRule) {
console.log(`Already enabled`)
return
}
currentRules.required_status_checks.contexts.push(codeFreezeRule.context)
await updateRules(currentRules)
console.log('Enabled code freeze')
} else {
if (!hasRule) {
console.log(`Not enabled`)
ijjk marked this conversation as resolved.
Show resolved Hide resolved
return
}
currentRules.required_status_checks.contexts =
currentRules.required_status_checks.contexts.filter(
(ctx) => ctx !== codeFreezeRule.context
)
await updateRules(currentRules)
console.log('Disabled code freeze')
}
}

main().catch((err) => {
console.error(err)
process.exit(1)
})
Loading