Skip to content

Commit d644884

Browse files
author
Peter Bengtsson
authored
Warn when trying to delete a feature (#50127)
1 parent 3fb553f commit d644884

3 files changed

Lines changed: 163 additions & 0 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Don't delete features
2+
3+
# **What it does**:
4+
# If the PR (against main) involves deletion of features, if any of
5+
# them are deletions or renames, post a comment, and ultimately
6+
# fail the check.
7+
# **Why we have it**:
8+
# If you delete the reference to an image, the English content is fine
9+
# because it no longer tries to use the feature that doesn't exist.
10+
# But this is not the case for translations.
11+
# **Who does it impact**: Docs content.
12+
13+
on:
14+
workflow_dispatch:
15+
pull_request:
16+
branches:
17+
- main
18+
paths:
19+
- 'data/features/**'
20+
21+
permissions:
22+
contents: read
23+
pull-requests: write
24+
25+
jobs:
26+
dont-delete-features:
27+
# It's 'docs-bot' that creates those PR from "Delete orphaned features"
28+
if: github.event.pull_request.user.login != 'docs-bot' && (github.repository == 'github/docs-internal' || github.repository == 'github/docs')
29+
runs-on: ubuntu-latest
30+
steps:
31+
- name: Check out repo
32+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
33+
34+
- uses: ./.github/actions/node-npm-setup
35+
36+
- name: Get comment markdown
37+
id: comment
38+
env:
39+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
run: npm run deleted-features-pr-comment
41+
42+
- name: Find possible previous comment
43+
if: ${{ steps.comment.outputs.markdown != '' }}
44+
uses: peter-evans/find-comment@d5fe37641ad8451bdd80312415672ba26c86575e
45+
id: findComment
46+
with:
47+
issue-number: ${{ github.event.number }}
48+
comment-author: 'github-actions[bot]'
49+
body-includes: '<!-- DELETED_FEATURES -->'
50+
51+
- name: Update comment
52+
if: ${{ steps.comment.outputs.markdown != '' }}
53+
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043
54+
with:
55+
comment-id: ${{ steps.findComment.outputs.comment-id }}
56+
issue-number: ${{ github.event.number }}
57+
body: ${{ steps.comment.outputs.markdown }}
58+
edit-mode: replace
59+
60+
- name: Ultimately fail the workflow for attention
61+
if: ${{ steps.comment.outputs.markdown != '' }}
62+
run: |
63+
echo "More than 1 feature was deleted as part of this PR."
64+
echo "See posted PR commented about how to get them back."
65+
exit 1

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"count-translation-corruptions": "tsx src/languages/scripts/count-translation-corruptions.ts",
2626
"debug": "cross-env NODE_ENV=development ENABLED_LANGUAGES=en nodemon --inspect src/frame/server.ts",
2727
"delete-orphan-translation-files": "tsx src/workflows/delete-orphan-translation-files.ts",
28+
"deleted-features-pr-comment": "tsx src/data-directory/scripts/deleted-features-pr-comment.ts",
2829
"dev": "cross-env npm start",
2930
"find-orphaned-assets": "node src/assets/scripts/find-orphaned-assets.js",
3031
"find-orphaned-features": "tsx src/data-directory/scripts/find-orphaned-features/index.ts",
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* This script is supposed to be used in Actions. When it's run in Actions
3+
* there will be an env var called GITHUB_REPOSITORY. If it's not there,
4+
* you can use this script as a CLI tool. For example:
5+
*
6+
* export GITHUB_TOKEN=github_pat_blablabla
7+
* npm run deleted-features-pr-comment -- github docs-internal main 2ba53b6a
8+
*
9+
*/
10+
11+
import * as github from '@actions/github'
12+
import core from '@actions/core'
13+
import { program } from 'commander'
14+
15+
const { GITHUB_TOKEN, GITHUB_REPOSITORY } = process.env
16+
17+
if (!GITHUB_TOKEN) {
18+
throw new Error(`GITHUB_TOKEN environment variable not set`)
19+
}
20+
21+
if (GITHUB_REPOSITORY) {
22+
const context = github.context
23+
24+
const owner = context.repo.owner
25+
const repo = context.payload.repository!.name
26+
const baseSHA = process.env.BASE_SHA || context.payload.pull_request!.base.sha
27+
const headSHA = process.env.HEAD_SHA || context.payload.pull_request!.head.sha
28+
29+
const markdown = await main(owner, repo, baseSHA, headSHA)
30+
core.setOutput('markdown', markdown)
31+
} else {
32+
program
33+
.description('Print a nice Markdown comment if there were features deleted in a PR.')
34+
.arguments('owner repo bash_sha head_sha')
35+
.parse(process.argv)
36+
37+
const args = program.args
38+
const [owner, repo, baseSHA, headSHA] = args
39+
console.log(await main(owner, repo, baseSHA, headSHA))
40+
}
41+
42+
async function main(owner: string, repo: string, baseSHA: string, headSHA: string) {
43+
if (!GITHUB_TOKEN) {
44+
throw new Error(`GITHUB_TOKEN environment variable not set`)
45+
}
46+
const octokit = github.getOctokit(GITHUB_TOKEN)
47+
// get the list of file changes from the PR
48+
const response = await octokit.rest.repos.compareCommitsWithBasehead({
49+
owner,
50+
repo,
51+
basehead: `${baseSHA}...${headSHA}`,
52+
})
53+
54+
const { files } = response.data
55+
56+
if (!files) return ''
57+
58+
const oldFilenames = []
59+
for (const file of files) {
60+
const { filename, status } = file
61+
if (!filename.startsWith('data/features')) continue
62+
63+
console.warn(`Feature involved in this PR: ${filename}; Status: ${status}`)
64+
if (status === 'removed') {
65+
// Bad
66+
oldFilenames.push(filename)
67+
} else if (status === 'renamed') {
68+
// Also bad
69+
const previousFilename = file.previous_filename
70+
oldFilenames.push(previousFilename)
71+
} else {
72+
console.warn(`${filename} was not removed or renamed. Skipping.`)
73+
}
74+
}
75+
76+
if (!oldFilenames.length) {
77+
console.warn("No old file names in this PR. And that's perfectly cool.")
78+
return ''
79+
}
80+
81+
let markdown = '⚠️ 🙀 **You deleted some features** 🙀 ⚠️\n\n'
82+
markdown +=
83+
"Even if you don't reference these features anymore, as of this branch, you should not delete them.\n"
84+
markdown += 'They might still be referenced in translated content.\n'
85+
markdown +=
86+
'The weekly "Delete orphaned features" workflow will worry about cleaning those up.\n\n'
87+
markdown += '**To *undo* these removals run this command:**\n\n'
88+
markdown += `
89+
\`\`\`sh
90+
git checkout origin/main -- ${oldFilenames.join(' ')}
91+
\`\`\`
92+
`
93+
94+
return markdown
95+
}
96+
97+
export default main

0 commit comments

Comments
 (0)