Skip to content

Commit

Permalink
chore(ci): add changelog check to ci (#9989)
Browse files Browse the repository at this point in the history
This PR is a spike on improving the Changelog in our release process. It
adds a workflow to our CI that checks to see if a PR updated the
CHANGELOG.md file.

In pairing on release, the hardest part is the release notes. If release
is going to be more approachable and sustainable, we need to spread the
burden of writing release notes, and the best person to write the
release notes for a particular PR is the person who wrote it or the
person who reviewed it. And the best time to do it is before it's
merged! (Not weeks or months after.)

I like reading [esbuild's release
notes](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md) and
tried to find out how Evan Wallace writes them. It seems like he just
adds a bullet point to the CHANGELOG.md file as the last commit before
merging a PR he writes or reviews. I'm not sure if it gets much simpler
than that, so I thought we could start there.

- If a user doesn't update the changelog:

Failing run:
https://github.com/redwoodjs/redwood/actions/runs/7850731400/job/21426621517?pr=9989

  Failing check:

<img width="675" alt="image"
src="https://github.com/redwoodjs/redwood/assets/32992335/97a1773f-317e-4c11-9ec1-2a73c3c40d96">

  Instructions in the check:

<img width="1532" alt="image"
src="https://github.com/redwoodjs/redwood/assets/32992335/21ec9ecf-263f-46dc-9632-00f1ff8cc084">

Some feedback I'm anticipating is: those instructions are hard to find,
this check should comment in the PR. Agree that if you don't know where
to look, you won't find them. But commenting in the PR complicates the
logic and get noisy fast (we've disabled every bot that comments in
threads). One more point: I think updating the Changelog should be on
the burden of maintainers, so as long as we know the process it should
work out. But happy for any feedback or ideas!
  • Loading branch information
jtoar committed Feb 16, 2024
1 parent 7fc0648 commit 43182f1
Show file tree
Hide file tree
Showing 6 changed files with 361 additions and 32 deletions.
10 changes: 10 additions & 0 deletions .github/actions/check_changelog/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: Check CHANGELOG.md
description: Checks if CHANGELOG.md has been updated

runs:
using: node20
main: check_changelog.mjs

inputs:
labels:
required: true
68 changes: 68 additions & 0 deletions .github/actions/check_changelog/check_changelog.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { getInput } from '@actions/core'
import { exec, getExecOutput } from '@actions/exec'
import github from '@actions/github'

async function main() {
// If the PR has the "changelog-ok" label, just pass.
const { labels } = JSON.parse(getInput('labels'))
const hasChangelogOkLabel = labels.some((label) => label.name === 'changelog-ok')
if (hasChangelogOkLabel) {
console.log('Skipping check because of the "changelog-ok" label')
return
}

// Check if the PR updates the Changelog.
await exec('git fetch origin main', [], { silent: true })
const { stdout } = await getExecOutput('git diff origin/main --name-only', [], { silent: true })
const changedFiles = stdout.toString().trim().split('\n').filter(Boolean)
const didUpdateChangelog = changedFiles.some((file) => file === 'CHANGELOG.md')
if (didUpdateChangelog) {
// Empty space here (and in subsequent `console.log`s) for formatting in the action.
console.log(
[
'',
"CHANGELOG.md was updated",
].join('\n')
)

return
}

const pr = github.context.payload.pull_request

// The lines here are long but it's about how they look in GitHub actions, not here.
// So if you make changes, cross check them with how they actually look in the action.
console.log(
[
'',
'📝 Update the Changelog',
'=======================',
'',
'Before this PR can be merged, you need to update the Changelog at CHANGELOG.md. Add a bullet point to the Unreleased section at the top of the file in the following format',
'',
'```',
"## Unreleased",
'',
" - PR title (#PR number)",
'',
" Body...",
'```',
'',
`"PR title" and "PR number" should be the title and number of the PR you're working on verbatim. But "Body" shouldn't necessarily be the same. Feel free to use it as a starting point though.`,
'',
'In writing the body, explain what this PR means for Redwood users. The more detail the better. E.g., is it a new feature? How do they use it? Code examples go a long way!',
'',
"Here are your PR's title, number, and body as a starting point:",
'',
'```',
`- ${pr.title} (#${pr.number})`,
'',
` ${pr.body}`,
'```',
].join('\n')
)

process.exitCode = 1
}

main()
10 changes: 10 additions & 0 deletions .github/actions/check_changelog/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "check_changelog",
"private": true,
"dependencies": {
"@actions/core": "1.10.1",
"@actions/exec": "1.1.1",
"@actions/github": "6.0.0"
},
"packageManager": "yarn@4.0.2"
}
237 changes: 237 additions & 0 deletions .github/actions/check_changelog/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
# This file is generated by running "yarn install" inside your project.
# Manual changes might be lost - proceed with caution!

__metadata:
version: 8
cacheKey: 10c0

"@actions/core@npm:1.10.1":
version: 1.10.1
resolution: "@actions/core@npm:1.10.1"
dependencies:
"@actions/http-client": "npm:^2.0.1"
uuid: "npm:^8.3.2"
checksum: 7a61446697a23dcad3545cf0634dedbdedf20ae9a0ee6ee977554589a15deb4a93593ee48a41258933d58ce0778f446b0d2c162b60750956fb75e0b9560fb832
languageName: node
linkType: hard

"@actions/exec@npm:1.1.1":
version: 1.1.1
resolution: "@actions/exec@npm:1.1.1"
dependencies:
"@actions/io": "npm:^1.0.1"
checksum: 4a09f6bdbe50ce68b5cf8a7254d176230d6a74bccf6ecc3857feee209a8c950ba9adec87cc5ecceb04110182d1c17117234e45557d72fde6229b7fd3a395322a
languageName: node
linkType: hard

"@actions/github@npm:6.0.0":
version: 6.0.0
resolution: "@actions/github@npm:6.0.0"
dependencies:
"@actions/http-client": "npm:^2.2.0"
"@octokit/core": "npm:^5.0.1"
"@octokit/plugin-paginate-rest": "npm:^9.0.0"
"@octokit/plugin-rest-endpoint-methods": "npm:^10.0.0"
checksum: 6f86f564e6ec5873c69ff23bed308cef5f964dbdb559c5415c1ba479517bf18352713a2a757c27f8f67a3d675fdd78446cf142b27762489f697edf9c58e72378
languageName: node
linkType: hard

"@actions/http-client@npm:^2.0.1, @actions/http-client@npm:^2.2.0":
version: 2.2.0
resolution: "@actions/http-client@npm:2.2.0"
dependencies:
tunnel: "npm:^0.0.6"
undici: "npm:^5.25.4"
checksum: 868fe8529d78beb72f84ea2486e232fa6f66abe00d6ec4591b98c37e762c3d812868a3548638d75b49917961fd10ba1556916b47b1e9e4b55c266e2013c3ae8e
languageName: node
linkType: hard

"@actions/io@npm:^1.0.1":
version: 1.1.3
resolution: "@actions/io@npm:1.1.3"
checksum: 5b8751918e5bf0bebd923ba917fb1c0e294401e7ff0037f32c92a4efa4215550df1f6633c63fd4efb2bdaae8711e69b9e36925857db1f38935ff62a5c92ec29e
languageName: node
linkType: hard

"@fastify/busboy@npm:^2.0.0":
version: 2.1.0
resolution: "@fastify/busboy@npm:2.1.0"
checksum: 7bb641080aac7cf01d88749ad331af10ba9ec3713ec07cabbe833908c75df21bd56249bb6173bdec07f5a41896b21e3689316f86684c06635da45f91ff4565a2
languageName: node
linkType: hard

"@octokit/auth-token@npm:^4.0.0":
version: 4.0.0
resolution: "@octokit/auth-token@npm:4.0.0"
checksum: 57acaa6c394c5abab2f74e8e1dcf4e7a16b236f713c77a54b8f08e2d14114de94b37946259e33ec2aab0566b26f724c2b71d2602352b59e541a9854897618f3c
languageName: node
linkType: hard

"@octokit/core@npm:^5.0.1":
version: 5.1.0
resolution: "@octokit/core@npm:5.1.0"
dependencies:
"@octokit/auth-token": "npm:^4.0.0"
"@octokit/graphql": "npm:^7.0.0"
"@octokit/request": "npm:^8.0.2"
"@octokit/request-error": "npm:^5.0.0"
"@octokit/types": "npm:^12.0.0"
before-after-hook: "npm:^2.2.0"
universal-user-agent: "npm:^6.0.0"
checksum: a1d2882373b4a33cd9f6e56d76bcc82e5589a477829fc3491b1ef471a8a83fa437b339a2c76d97d9e8ea4ca12bf3ebf32e66119ba16977e542d98f1f5dd3c994
languageName: node
linkType: hard

"@octokit/endpoint@npm:^9.0.0":
version: 9.0.4
resolution: "@octokit/endpoint@npm:9.0.4"
dependencies:
"@octokit/types": "npm:^12.0.0"
universal-user-agent: "npm:^6.0.0"
checksum: f1c857c5d85afa9d7e8857f7f97dbec28d3b6ab1dc21fe35172f1bc9e5512c8a3a26edabf6b2d83bb60d700f7ad290c96be960496aa83606095630edfad06db4
languageName: node
linkType: hard

"@octokit/graphql@npm:^7.0.0":
version: 7.0.2
resolution: "@octokit/graphql@npm:7.0.2"
dependencies:
"@octokit/request": "npm:^8.0.1"
"@octokit/types": "npm:^12.0.0"
universal-user-agent: "npm:^6.0.0"
checksum: 96e5d6b970be60877134cc147b9249534f3a79d691b9932d731d453426fa1e1a0a36111a1b0a6ab43d61309c630903a65db5559b5c800300dc26cf588f50fea8
languageName: node
linkType: hard

"@octokit/openapi-types@npm:^19.1.0":
version: 19.1.0
resolution: "@octokit/openapi-types@npm:19.1.0"
checksum: ae8081f52b797b91a12d4f6cddc475699c9d34b06645b337adc77d30b583d8fe8506597a45c42f8f1a96bfb2a9d092cee257d8a65d718bfeed23a0d153448eea
languageName: node
linkType: hard

"@octokit/plugin-paginate-rest@npm:^9.0.0":
version: 9.1.5
resolution: "@octokit/plugin-paginate-rest@npm:9.1.5"
dependencies:
"@octokit/types": "npm:^12.4.0"
peerDependencies:
"@octokit/core": ">=5"
checksum: a17055dff8fde5ebc03bf935294ffa4605ed714cb15252f0fa63cda1b95e738fafb5ab9748b18fbdfa5615d5f6686cbf193c6d6426e7dc4fd1dda91c87263f3b
languageName: node
linkType: hard

"@octokit/plugin-rest-endpoint-methods@npm:^10.0.0":
version: 10.2.0
resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.2.0"
dependencies:
"@octokit/types": "npm:^12.3.0"
peerDependencies:
"@octokit/core": ">=5"
checksum: 4d00a2334753955f0c3841ba8fc0880c093b94838e011864ee737d958d2d64e3d45d34fa4c8b64bccf9e13c6de81318cbd6e2b24df37992941d12f54def28432
languageName: node
linkType: hard

"@octokit/request-error@npm:^5.0.0":
version: 5.0.1
resolution: "@octokit/request-error@npm:5.0.1"
dependencies:
"@octokit/types": "npm:^12.0.0"
deprecation: "npm:^2.0.0"
once: "npm:^1.4.0"
checksum: e72a4627120de345b54876a1f007664095e5be9d624fce2e14fccf7668cd8f5e4929d444d8fc085d48e1fb5cd548538453974aab129a669101110d6679dce6c6
languageName: node
linkType: hard

"@octokit/request@npm:^8.0.1, @octokit/request@npm:^8.0.2":
version: 8.2.0
resolution: "@octokit/request@npm:8.2.0"
dependencies:
"@octokit/endpoint": "npm:^9.0.0"
"@octokit/request-error": "npm:^5.0.0"
"@octokit/types": "npm:^12.0.0"
universal-user-agent: "npm:^6.0.0"
checksum: 0789edd3b600c5b7ca74089e2842b7bb679a0ad1ec56e5dda54f052d2dd266ac8e6e2eb3c34ba57962066f0770444bf1e99805fd2d762a47776f567beafcf038
languageName: node
linkType: hard

"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.3.0, @octokit/types@npm:^12.4.0":
version: 12.4.0
resolution: "@octokit/types@npm:12.4.0"
dependencies:
"@octokit/openapi-types": "npm:^19.1.0"
checksum: b52b3fd8af307a1868846991f8376548a790814b20639dee1110271a768c0489081970df893ca2230f6285066003230d22f5877eeac90418971a475c79808241
languageName: node
linkType: hard

"before-after-hook@npm:^2.2.0":
version: 2.2.3
resolution: "before-after-hook@npm:2.2.3"
checksum: 0488c4ae12df758ca9d49b3bb27b47fd559677965c52cae7b335784724fb8bf96c42b6e5ba7d7afcbc31facb0e294c3ef717cc41c5bc2f7bd9e76f8b90acd31c
languageName: node
linkType: hard

"check_changelog@workspace:.":
version: 0.0.0-use.local
resolution: "check_changelog@workspace:."
dependencies:
"@actions/core": "npm:1.10.1"
"@actions/exec": "npm:1.1.1"
"@actions/github": "npm:6.0.0"
languageName: unknown
linkType: soft

"deprecation@npm:^2.0.0":
version: 2.3.1
resolution: "deprecation@npm:2.3.1"
checksum: 23d688ba66b74d09b908c40a76179418acbeeb0bfdf218c8075c58ad8d0c315130cb91aa3dffb623aa3a411a3569ce56c6460de6c8d69071c17fe6dd2442f032
languageName: node
linkType: hard

"once@npm:^1.4.0":
version: 1.4.0
resolution: "once@npm:1.4.0"
dependencies:
wrappy: "npm:1"
checksum: 5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0
languageName: node
linkType: hard

"tunnel@npm:^0.0.6":
version: 0.0.6
resolution: "tunnel@npm:0.0.6"
checksum: e27e7e896f2426c1c747325b5f54efebc1a004647d853fad892b46d64e37591ccd0b97439470795e5262b5c0748d22beb4489a04a0a448029636670bfd801b75
languageName: node
linkType: hard

"undici@npm:^5.25.4":
version: 5.28.3
resolution: "undici@npm:5.28.3"
dependencies:
"@fastify/busboy": "npm:^2.0.0"
checksum: 3c559ae50ef3104b7085251445dda6f4de871553b9e290845649d2f80b06c0c9cfcdf741b0029c6b20d36c82e6a74dc815b139fa9a26757d70728074ca6d6f5c
languageName: node
linkType: hard

"universal-user-agent@npm:^6.0.0":
version: 6.0.1
resolution: "universal-user-agent@npm:6.0.1"
checksum: 5c9c46ffe19a975e11e6443640ed4c9e0ce48fcc7203325757a8414ac49940ebb0f4667f2b1fa561489d1eb22cb2d05a0f7c82ec20c5cba42e58e188fb19b187
languageName: node
linkType: hard

"uuid@npm:^8.3.2":
version: 8.3.2
resolution: "uuid@npm:8.3.2"
bin:
uuid: dist/bin/uuid
checksum: bcbb807a917d374a49f475fae2e87fdca7da5e5530820ef53f65ba1d12131bd81a92ecf259cc7ce317cbe0f289e7d79fdfebcef9bfa3087c8c8a2fa304c9be54
languageName: node
linkType: hard

"wrappy@npm:1":
version: 1.0.2
resolution: "wrappy@npm:1.0.2"
checksum: 56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0
languageName: node
linkType: hard
33 changes: 33 additions & 0 deletions .github/workflows/check-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: 📝 Check CHANGELOG.md

on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]

# Cancel in-progress runs of this workflow.
# See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-only-cancel-in-progress-jobs-or-runs-for-the-current-workflow.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
check-changelog:
name: 📝 Check CHANGELOG.md
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Enable Corepack
run: corepack enable

- uses: actions/setup-node@v4
with:
node-version: 20

- run: yarn install
working-directory: ./.github/actions/check_changelog

- name: Check CHANGELOG.md
uses: ./.github/actions/check_changelog
with:
labels: '{ "labels": ${{ toJSON(github.event.pull_request.labels) }} }'
Loading

0 comments on commit 43182f1

Please sign in to comment.