Detect when SQL schema or user grants change #46
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Check PR for configuration and SQL changes | |
on: | |
pull_request: | |
types: [opened, synchronize, reopened] | |
paths: | |
- 'test/config-next/*.json' | |
- 'test/config-next/*.yaml' | |
- 'test/config-next/*.yml' | |
- 'sa/db-users/*.sql' | |
- 'sa/db-next/**/*.sql' | |
- 'sa/db/**/*.sql' | |
jobs: | |
check-changes: | |
runs-on: ubuntu-latest | |
permissions: | |
pull-requests: write | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v2 | |
- name: Comment PR | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
// As of 2024-02, there is no way to determine which watched path triggered a github workflow. | |
// Vanilla javascript does not support double star globs (**), so instead the github-script | |
// action provides access to a globbing library which does. The monitoredPaths array should | |
// match the paths array above. | |
const monitoredPaths = [ | |
'test/config-next/*.json', | |
'test/config-next/*.yaml', | |
'test/config-next/*.yml', | |
'sa/db-users/*.sql', | |
'sa/db-next/**/*.sql', | |
'sa/db/**/*.sql', | |
] | |
const globber = await glob.create(monitoredPaths.join('\n')) | |
// Contains the full path of every file in the checkedout repository that matches the monitoredPaths array. | |
const allFiles = await globber.glob() | |
const commentMarker = '<!-- deployment_ticket_checkX29 -->'; | |
const prAuthor = context.payload.pull_request.user.login; | |
const commentPreamble = `${commentMarker}\n@${prAuthor},\n`; | |
const commentConfigChange = `This PR appears to contain configuration changes. Please ensure that a corresponding deployment ticket has been filed with the new configuration values.\n`; | |
const commentSQLChange = `This PR appears to contain SQL schema or user grant changes. Please ensure that a corresponding deployment ticket has been filed with the new migrations.\n`; | |
// Build this string as appropriate changed files are detected. | |
let commentBody = `${commentPreamble}` | |
const { owner, repo, number: issue_number } = context.issue; | |
const iterator = github.paginate.iterator('GET /repos/{owner}/{repo}/pulls/{pull_number}/files', { | |
owner, | |
repo, | |
pull_number: issue_number, | |
per_page: 100, | |
}); | |
let filesChanged = [] | |
for await (const {data} of iterator) { | |
filesChanged = [...filesChanged, ...data.map(fileData => fileData.filename)]; | |
} | |
for (const cFile of filesChanged) { | |
for (const aFile of allFiles) { | |
if (aFile.includes(cFile)) { | |
commentBody += cFile.concat(" triggered this workflow.\n"); | |
} | |
} | |
} | |
const issueRegexp = /IN-\d+/; | |
// Get PR body and all issue comments. | |
const prBody = context.payload.pull_request.body; | |
const comments = await github.rest.issues.listComments({ | |
owner, | |
repo, | |
issue_number | |
}); | |
if (issueRegexp.test(prBody) || comments.data.some(c => issueRegexp.test(c.body))) { | |
// Issue number exists in PR body or comments. | |
return; | |
} | |
if (comments.data.find(c => c.body.includes(commentMarker))) { | |
// Comment already exists. | |
return; | |
} | |
// No issue number or comment were found, post the comment. | |
await github.rest.issues.createComment({ | |
owner, | |
repo, | |
issue_number, | |
body: commentBody | |
}); | |
github-token: ${{ secrets.GITHUB_TOKEN }} |