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 all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/code_freeze.yml
@@ -0,0 +1,44 @@
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

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: 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
@@ -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(`Already disabled`)
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)
})