Skip to content

ci: Add workflow to automatically add external contributors to CHANGELOG.md #12428

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

Merged
merged 14 commits into from
Jun 13, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,44 @@ jobs:
message: |
⚠️ This PR is opened against **master**. You probably want to open it against **develop**.

job_external_contributor:
name: External Contributors
needs: job_install_deps
runs-on: ubuntu-20.04
if: |
github.event_name == 'pull_request'
&& (github.action == 'opened' || github.action == 'reopened')
Copy link
Member Author

Choose a reason for hiding this comment

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

do not run this on each update, as it is kind of wasteful (it should not actually error, just unnecessary computation)

&& github.event.pull_request.author_association != 'COLLABORATOR'
&& github.event.pull_request.author_association != 'MEMBER'
&& github.event.pull_request.author_association != 'OWNER'
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: 'package.json'
- name: Check dependency cache
uses: actions/cache/restore@v4
with:
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
key: ${{ needs.job_install_deps.outputs.dependency_cache_key }}
fail-on-cache-miss: true

- name: Add external contributor to CHANGELOG.md
uses: ./dev-packages/external-contributor-gh-action
with:
name: ${{ github.event.pull_request.user.login }}
- name: Create PR with changes
uses: peter-evans/create-pull-request@v6
with:
commit-message: "ref: Add external contributor to CHANGELOG.md"
title: "ref: Add external contributor to CHANGELOG.md"
branch: 'external-contributor/patch-${{ github.event.pull_request.user.login }}'
delete-branch: true
body: This PR adds the external contributor to the CHANGELOG.md file, so that they are credited for their contribution.

job_build:
name: Build
needs: [job_get_metadata, job_install_deps]
Expand Down
14 changes: 14 additions & 0 deletions dev-packages/external-contributor-gh-action/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
extends: ['../../.eslintrc.js'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 'latest',
},

overrides: [
{
files: ['*.mjs'],
extends: ['@sentry-internal/sdk/src/base'],
},
],
};
9 changes: 9 additions & 0 deletions dev-packages/external-contributor-gh-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: 'external-contributor-gh-action'
description: 'Add external contributors to CHANGELOG.md'
inputs:
name:
required: true
description: 'The name of the external contributor'
runs:
using: 'node20'
main: 'index.mjs'
72 changes: 72 additions & 0 deletions dev-packages/external-contributor-gh-action/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { promises as fs } from 'node:fs';
import path from 'node:path';
import * as core from '@actions/core';

const UNRELEASED_HEADING = `## Unreleased

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
`;

const contributorMessageRegex = /Work in this release was contributed by (.+)\. Thank you for your contribution!/;

async function run() {
const { getInput } = core;

const name = getInput('name');

if (!name) {
return;
}

const ghUserName = name.startsWith('@') ? name : `@${name}`;

const cwd = process.cwd();
const changelogFilePath = path.resolve(cwd, 'CHANGELOG.md');

const changelogStr = await fs.readFile(changelogFilePath, 'utf8');

// Find the unreleased section
const start = changelogStr.indexOf(UNRELEASED_HEADING) + UNRELEASED_HEADING.length;
const end = changelogStr.slice(start).indexOf('## ');

const inBetween = changelogStr.slice(start, start + end);

const existing = contributorMessageRegex.exec(inBetween);

// If the contributor message already exists, add the new contributor to the list
if (existing) {
const users = existing[1].split(/(?:,? and )|(?:, )/);
if (!users.includes(ghUserName)) {
users.push(ghUserName);
}

const formatter = new Intl.ListFormat('en', {
style: 'long',
type: 'conjunction',
});

const newContributors = formatter.format(users);
const newChangelog = changelogStr.replace(
contributorMessageRegex,
`Work in this release was contributed by ${newContributors}. Thank you for your contribution!`,
);

fs.writeFile(changelogFilePath, newChangelog);

// eslint-disable-next-line no-console
console.log('Added contributor to list of existing contributors.');
return;
}

// If the contributor message does not exist, add it
const newChangelog = changelogStr.replace(
UNRELEASED_HEADING,
`${UNRELEASED_HEADING}\nWork in this release was contributed by ${ghUserName}. Thank you for your contribution!\n`,
);
fs.writeFile(changelogFilePath, newChangelog);

// eslint-disable-next-line no-console
console.log('Added contributor message.');
}

run();
22 changes: 22 additions & 0 deletions dev-packages/external-contributor-gh-action/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "@sentry-internal/external-contributor-gh-action",
"description": "An internal Github Action to add external contributors to the CHANGELOG.md file.",
"version": "8.8.0",
"license": "MIT",
"engines": {
"node": ">=18"
},
"private": true,
"main": "index.mjs",
"type": "module",
"scripts": {
"lint": "eslint . --format stylish",
"fix": "eslint . --format stylish --fix"
},
"dependencies": {
"@actions/core": "1.10.1"
},
"volta": {
"extends": "../../package.json"
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"dev-packages/overhead-metrics",
"dev-packages/test-utils",
"dev-packages/size-limit-gh-action",
"dev-packages/external-contributor-gh-action",
"dev-packages/rollup-utils"
],
"devDependencies": {
Expand Down
Loading