Skip to content

Commit

Permalink
fix: add release.yml input to rerun jobs on a merged release
Browse files Browse the repository at this point in the history
  • Loading branch information
lukekarrys committed Feb 7, 2023
1 parent 6a1dcac commit 46d1d14
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 56 deletions.
16 changes: 12 additions & 4 deletions .github/workflows/release.yml
Expand Up @@ -4,6 +4,10 @@ name: Release

on:
workflow_dispatch:
inputs:
release-pr:
description: a release PR number to rerun release jobs on
type: string
push:
branches:
- main
Expand Down Expand Up @@ -53,7 +57,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx --offline template-oss-release-please ${{ github.ref_name }} ${{ github.event_name }}
npx --offline template-oss-release-please "${{ github.ref_name }}" "${{ inputs.release-pr }}"
- name: Post Pull Request Comment
if: steps.release.outputs.pr-number
uses: actions/github-script@v6
Expand All @@ -76,7 +80,7 @@ jobs:
body += `Release workflow run: ${workflow.html_url}\n\n#### Force CI to Update This Release\n\n`
body += `This PR will be updated and CI will run for every non-\`chore:\` commit that is pushed to \`main\`. `
body += `To force CI to update this PR, run this command:\n\n`
body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME} -R ${owner}/${repo}\n\`\`\``
body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME} -R ${owner}/${repo} -f release-pr=${issue_number}\n\`\`\``
if (commentId) {
await github.rest.issues.updateComment({ owner, repo, comment_id: commentId, body })
Expand Down Expand Up @@ -378,10 +382,14 @@ jobs:
with:
script: |
const { PR_NUMBER: issue_number, RESULT } = process.env
const { repo: { owner, repo } } = context
const { runId, repo: { owner, repo } } = context
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number })
const updateComment = comments.find(c => c.user.login === 'github-actions[bot]' && c.body.startsWith('## Release Workflow\n\n'))
const updateComment = comments.find(c =>
c.user.login === 'github-actions[bot]' &&
c.body.startsWith('## Release Workflow\n\n') &&
c.body.includes(runId)
)
if (updateComment) {
console.log('Found comment to update:', JSON.stringify(updateComment, null, 2))
Expand Down
4 changes: 2 additions & 2 deletions bin/release-please.js
Expand Up @@ -4,7 +4,7 @@ const core = require('@actions/core')
const main = require('../lib/release-please/index.js')

const dryRun = !process.env.CI
const [branch, eventName] = process.argv.slice(2)
const [branch, forcePullRequest] = process.argv.slice(2)

const debugPr = (val) => {
if (dryRun) {
Expand Down Expand Up @@ -45,7 +45,7 @@ main({
repo: process.env.GITHUB_REPOSITORY,
dryRun,
branch,
force: eventName === 'workflow_dispatch',
forcePullRequest: forcePullRequest ? +forcePullRequest : null,
}).then(({ pr, release, releases }) => {
if (pr) {
debugPr(pr)
Expand Down
16 changes: 12 additions & 4 deletions lib/content/release.yml
Expand Up @@ -2,6 +2,10 @@ name: Release

on:
workflow_dispatch:
inputs:
release-pr:
description: a release PR number to rerun release jobs on
type: string
push:
branches:
{{#each branches}}
Expand Down Expand Up @@ -30,7 +34,7 @@ jobs:
env:
GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
run: |
{{ rootNpxPath }} --offline template-oss-release-please $\{{ github.ref_name }} $\{{ github.event_name }}
{{ rootNpxPath }} --offline template-oss-release-please "$\{{ github.ref_name }}" "$\{{ inputs.release-pr }}"
- name: Post Pull Request Comment
if: steps.release.outputs.pr-number
uses: actions/github-script@v6
Expand All @@ -53,7 +57,7 @@ jobs:
body += `Release workflow run: ${workflow.html_url}\n\n#### Force CI to Update This Release\n\n`
body += `This PR will be updated and CI will run for every non-\`chore:\` commit that is pushed to \`{{ defaultBranch }}\`. `
body += `To force CI to update this PR, run this command:\n\n`
body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME} -R ${owner}/${repo}\n\`\`\``
body += `\`\`\`\ngh workflow run release.yml -r ${REF_NAME} -R ${owner}/${repo} -f release-pr=${issue_number}\n\`\`\``
if (commentId) {
await github.rest.issues.updateComment({ owner, repo, comment_id: commentId, body })
Expand Down Expand Up @@ -182,10 +186,14 @@ jobs:
with:
script: |
const { PR_NUMBER: issue_number, RESULT } = process.env
const { repo: { owner, repo } } = context
const { runId, repo: { owner, repo } } = context
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number })
const updateComment = comments.find(c => c.user.login === 'github-actions[bot]' && c.body.startsWith('## Release Workflow\n\n'))
const updateComment = comments.find(c =>
c.user.login === 'github-actions[bot]' &&
c.body.startsWith('## Release Workflow\n\n') &&
c.body.includes(runId)
)
if (updateComment) {
console.log('Found comment to update:', JSON.stringify(updateComment, null, 2))
Expand Down
132 changes: 98 additions & 34 deletions lib/release-please/index.js
Expand Up @@ -20,7 +20,18 @@ const omit = (obj, ...keys) => {
return res
}

const getReleaseArtifacts = async ({ dryRun, github, baseBranch }) => {
const getManifest = async ({ repo: fullRepo, token, branch }) => {
const fullRepoParts = fullRepo.split('/')
const github = await RP.GitHub.create({
owner: fullRepoParts[0],
repo: fullRepoParts[1],
token,
})

const { octokit, repository: { owner, repo, defaultBranch } } = github

const baseBranch = branch ?? defaultBranch

// This is mostly for testing and debugging. Use environs with the
// format `RELEASE_PLEASE_<manfiestOverrideConfigName>` (eg
// `RELEASE_PLEASE_lastReleaseSha=<SHA>`) to set one-off config items
Expand All @@ -37,10 +48,56 @@ const getReleaseArtifacts = async ({ dryRun, github, baseBranch }) => {
Object.fromEntries(manifestOverrides)
)

let pullRequests
let releases
return {
github,
manifest,
octokit,
owner,
repo,
baseBranch,
}
}

const getReleasesFromPr = async ({ manifest, github, number }) => {
const baseUrl = `https://github.com/${github.repository.owner}/${github.repository.repo}`
// get the release please formatted pull request
let pullRequest
const prGenerator = github.pullRequestIterator(this.targetBranch, 'MERGED', 200, false)
for await (const pr of prGenerator) {
if (pr.number === number) {
pullRequest = pr
break
}
}
const strategiesByPath = await manifest.getStrategiesByPath()
const releases = []
for (const path in manifest.repositoryConfig) {
const config = manifest.repositoryConfig[path]
const release = await strategiesByPath[path].buildRelease(pullRequest)
if (release) {
const { tag, ...rest } = release
releases.push({
...rest,
...tag.version,
tagName: tag.toString(),
version: tag.version.toString(),
path,
draft: false,
url: `${baseUrl}/releases/tag/${tag.toString()}`,
prerelease: config.prerelease && !!tag.version.preRelease,
})
}
}
return releases
}

const getReleaseArtifacts = async ({ dryRun, manifest, forceReleases }) => {
let pullRequests = []
let releases = []

if (dryRun) {
if (forceReleases) {
releases = forceReleases
} else if (dryRun) {
pullRequests = await manifest.buildPullRequests()
releases = await manifest.buildReleases()
} else {
Expand All @@ -54,26 +111,15 @@ const getReleaseArtifacts = async ({ dryRun, github, baseBranch }) => {
}
}

const forcePullRequest = async ({ octokit, owner, repo, baseBranch }) => {
const { data: releasePrs } = await octokit.pulls.list({
owner,
repo,
head: `release-please--branches--${baseBranch}`,
})

if (releasePrs.length !== 1) {
throw new Error(`Found ${releasePrs.length} matching PRs, expected 1`)
}

const [releasePr] = releasePrs
// XXX(hack): to get release please to recreate a pull request it needs
// to have a different body string so we append a message a message that CI
// is running. This will force release-please to rebase the PR but it
// wont update the body again, so we only append to it.
const touchPullRequest = async ({ octokit, owner, repo, releasePr }) => {
const id = process.env.GITHUB_RUN_ID
? `by https://github.com/${owner}/${repo}/actions/runs/${process.env.GITHUB_RUN_ID}`
: `manually starting at ${new Date().toJSON()}`

// XXX(hack): to get release please to recreate a pull request it needs
// to have a different body string so we append a message a message that CI
// is running. This will force release-please to rebase the PR but it
// wont update the body again, so we only append to it.
await octokit.pulls.update({
owner,
repo,
Expand All @@ -82,33 +128,51 @@ const forcePullRequest = async ({ octokit, owner, repo, baseBranch }) => {
})
}

const main = async ({ repo: _fullRepo, token, dryRun, branch, force }) => {
const main = async ({ repo: fullRepo, token, dryRun, branch, forcePullRequest }) => {
if (!token) {
throw new Error('Token is required')
}

if (!_fullRepo) {
if (!fullRepo) {
throw new Error('Repo is required')
}

const fullRepo = _fullRepo.split('/')
const github = await RP.GitHub.create({
owner: fullRepo[0],
repo: fullRepo[1],
token,
})
const {
github,
octokit,
repository: { owner, repo, defaultBranch },
} = github
manifest,
owner,
repo,
baseBranch,
} = await getManifest({ repo: fullRepo, token, branch })

const baseBranch = branch ?? defaultBranch
let forceReleases = null

if (forcePullRequest) {
const { data: releasePr } = await octokit.rest.pulls.get({
owner,
repo,
pull_number: forcePullRequest,
})

if (force) {
await forcePullRequest({ octokit, owner, repo, baseBranch })
if (!releasePr) {
throw new Error(`Could not find PR from number: ${forcePullRequest}`)
}

if (releasePr.state === 'open') {
await touchPullRequest({ octokit, owner, repo, releasePr })
} else if (releasePr.state === 'closed' && releasePr.merged) {
forceReleases = await getReleasesFromPr({ manifest, github, number: releasePr.number })
} else {
throw new Error(`Could not run workflow on PR with wrong state: ${JSON.stringify(
releasePr,
null,
2
)}`)
}
}

const { pullRequests, releases } = await getReleaseArtifacts({ dryRun, github, baseBranch })
const { pullRequests, releases } = await getReleaseArtifacts({ dryRun, manifest, forceReleases })

// We only ever get a single pull request with our current release-please settings
// Update this if we start creating individual PRs per workspace release
Expand Down

0 comments on commit 46d1d14

Please sign in to comment.