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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: set up multi-branch automated release #3110

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
21 changes: 11 additions & 10 deletions .github/workflows/release-create-pr.yml
Expand Up @@ -6,17 +6,20 @@ permissions:
on:
workflow_dispatch:
inputs:
version:
description: 'The version number to release (has priority over release_type)'
type: string
major_branch:
description: Major version branch
type: choice
default: main
options:
- main
- v5.x
release_type:
description: Type of release
type: choice
default: patch
options:
- patch
- minor
- major

jobs:
create-pr:
Expand All @@ -26,11 +29,10 @@ jobs:
contents: write
pull-requests: write

outputs:
version: ${{ steps.bump.outputs.version }}

steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.major_branch }}
- uses: actions/setup-node@v4
with:
node-version: '20'
Expand All @@ -41,7 +43,7 @@ jobs:
- name: Change version number and push
id: bump
run: |
npm version ${{ inputs.version || inputs.release_type }} --git-tag-version=false
npm version ${{ inputs.release_type }} --git-tag-version=false
VERSION=`jq -r ".version" package.json`
RELEASE_BRANCH="release/v$VERSION"
git add -u
Expand All @@ -52,6 +54,5 @@ jobs:
uses: actions/github-script@v7
with:
script: |
const defaultBranch = "${{ github.event.repository.default_branch }}"
const versionTag = "v${{ steps.bump.outputs.version }}"
await require('./scripts/release').generatePr({ github, context, defaultBranch, versionTag })
await require('./scripts/release').generatePr({ github, context, versionTag })
16 changes: 6 additions & 10 deletions .github/workflows/release.yml
Expand Up @@ -3,7 +3,7 @@ name: Create release
on:
push:
branches:
- main
- main
paths:
- package.json

Expand All @@ -26,12 +26,9 @@ jobs:
const version = require("./package.json").version
const versionTag = `v${version}`

const { data: releases } = await github.rest.repos.listReleases({
owner,
repo
})
const previousReleaseTag = await require('./scripts/release').previousReleaseTag({ github, context, versionTag })

if (versionTag !== releases[0]?.tag_name) {
if (versionTag !== previousReleaseTag) {
return versionTag
}

Expand All @@ -55,18 +52,17 @@ jobs:
- run: npm install -g npm@latest
- run: npm install
- name: Create NPM release
run: npm publish --provenance --access public
run: npm publish --provenance --access public --tag latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: node scripts/generate-undici-types-package-json.js
- run: npm publish --provenance
- run: npm publish --provenance --access public --tag latest
working-directory: './types'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub release
uses: actions/github-script@v7
with:
script: |
const defaultBranch = "${{ github.event.repository.default_branch }}"
const versionTag = "${{ needs.check-release-version.outputs.release-version }}"
await require('./scripts/release').release({ github, context, defaultBranch, versionTag })
await require('./scripts/release').release({ github, context, versionTag })
54 changes: 40 additions & 14 deletions scripts/release.js
Expand Up @@ -2,18 +2,37 @@

// Called from .github/workflows

const generateReleaseNotes = async ({ github, owner, repo, versionTag, defaultBranch }) => {
const { data: releases } = await github.rest.repos.listReleases({
owner,
repo
})
// The following two variables should be updated per major version release branch (main, v5.x, etc)
const VERSION_TAG_PREFIX = 'v6.'
const BRANCH = 'main'

const getLatestRelease = async ({ github, owner, repo }) => {
for await (const { data } of github.paginate.iterator(
github.rest.repos.listReleases,
{
owner,
repo
}
)) {
const latestRelease = data.find((r) => r.tag_name.startsWith(VERSION_TAG_PREFIX))

if (latestRelease) {
return latestRelease
}
}

throw new Error(`Could not find latest release of ${VERSION_TAG_PREFIX}x`)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this will work when we cut v7. we should really use semver here instead of relying on filters.


const generateReleaseNotes = async ({ github, owner, repo, versionTag }) => {
const previousRelease = await getLatestRelease({ github, owner, repo, versionTag })

const { data: { body } } = await github.rest.repos.generateReleaseNotes({
owner,
repo,
tag_name: versionTag,
target_commitish: defaultBranch,
previous_tag_name: releases[0]?.tag_name
target_commitish: `heads/${BRANCH}`,
previous_tag_name: previousRelease.tag_name
})

const bodyWithoutReleasePr = body.split('\n')
Expand All @@ -23,29 +42,29 @@ const generateReleaseNotes = async ({ github, owner, repo, versionTag, defaultBr
return bodyWithoutReleasePr
}

const generatePr = async ({ github, context, defaultBranch, versionTag }) => {
const generatePr = async ({ github, context, versionTag }) => {
const { owner, repo } = context.repo
const releaseNotes = await generateReleaseNotes({ github, owner, repo, versionTag, defaultBranch })
const releaseNotes = await generateReleaseNotes({ github, owner, repo, versionTag })

await github.rest.pulls.create({
owner,
repo,
head: `release/${versionTag}`,
base: defaultBranch,
base: BRANCH,
title: `[Release] ${versionTag}`,
body: releaseNotes
})
}

const release = async ({ github, context, defaultBranch, versionTag }) => {
const release = async ({ github, context, versionTag }) => {
const { owner, repo } = context.repo
const releaseNotes = await generateReleaseNotes({ github, owner, repo, versionTag, defaultBranch })
const releaseNotes = await generateReleaseNotes({ github, owner, repo, versionTag })

await github.rest.repos.createRelease({
owner,
repo,
tag_name: versionTag,
target_commitish: defaultBranch,
target_commitish: BRANCH,
name: versionTag,
body: releaseNotes,
draft: false,
Expand All @@ -65,7 +84,14 @@ const release = async ({ github, context, defaultBranch, versionTag }) => {
}
}

const previousReleaseTag = async ({ github, context, versionTag }) => {
const { owner, repo } = context.repo
const previousRelease = await getLatestRelease({ github, owner, repo, versionTag })
return previousRelease.tag_name
}

module.exports = {
generatePr,
release
release,
previousReleaseTag
}