From 501c6642bf4e4f273cac8e030bc7c32d5d78f4d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 18:14:41 +0000 Subject: [PATCH 01/11] Add local changeset check action Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../check-for-changed-files/action.yml | 25 +++ .../actions/check-for-changed-files/index.js | 162 ++++++++++++++++++ .github/workflows/check_for_changeset.yml | 6 +- 3 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 .github/actions/check-for-changed-files/action.yml create mode 100644 .github/actions/check-for-changed-files/index.js diff --git a/.github/actions/check-for-changed-files/action.yml b/.github/actions/check-for-changed-files/action.yml new file mode 100644 index 00000000000..9faccfd7859 --- /dev/null +++ b/.github/actions/check-for-changed-files/action.yml @@ -0,0 +1,25 @@ +name: 'Check for Changed Files' +description: 'Require changed files in a pull request' +inputs: + file-pattern: + description: 'Glob pattern for changed file to check for' + required: true + prereq-pattern: + description: 'Glob pattern that guards whether the action will run' + required: false + default: '**' + skip-label: + description: 'Label to trigger skipping the check' + required: false + default: '' + failure-message: + description: 'String template used when the check fails' + required: false + default: 'the prerequisite file pattern ${prereq-pattern} matched changed files in the pull request, but the ${file-pattern} pattern did NOT and the ${skip-label} label is not set' + token: + description: 'GitHub token to use to list the pull request files' + required: false + default: '' +runs: + using: 'node20' + main: 'index.js' diff --git a/.github/actions/check-for-changed-files/index.js b/.github/actions/check-for-changed-files/index.js new file mode 100644 index 00000000000..db66075ffab --- /dev/null +++ b/.github/actions/check-for-changed-files/index.js @@ -0,0 +1,162 @@ +const fs = require('node:fs') + +const apiVersion = '2022-11-28' +const userAgent = 'primer-react-check-for-changed-files' + +main().catch(error => { + fail(error.message) +}) + +async function main() { + const payload = readEventPayload() + const inputs = readInputs() + + if (!payload || !payload.pull_request || !payload.repository || process.env.GITHUB_EVENT_NAME !== 'pull_request') { + info(`${JSON.stringify(process.env.GITHUB_EVENT_NAME)} is not a full 'pull_request' event; skipping`) + return + } + + const labels = payload.pull_request.labels.map(label => label.name) + if (inputs.skipLabel && labels.includes(inputs.skipLabel)) { + info(`the skip label ${JSON.stringify(inputs.skipLabel)} is set`) + return + } + + const filenames = await listChangedFiles(payload, inputs.token) + if (!anyFileMatches(filenames, inputs.preReqPattern)) { + info( + `the prerequisite ${JSON.stringify(inputs.preReqPattern)} file pattern did not match any changed files of the pull request`, + ) + return + } + + if (anyFileMatches(filenames, inputs.filePattern)) { + info(`the ${JSON.stringify(inputs.filePattern)} file pattern matched the changed files of the pull request`) + return + } + + fail(formatFailureMessage(inputs)) +} + +function readEventPayload() { + const eventPath = process.env.GITHUB_EVENT_PATH + if (!eventPath) { + return undefined + } + return JSON.parse(fs.readFileSync(eventPath, 'utf8')) +} + +function readInputs() { + return { + filePattern: getInput('file-pattern'), + preReqPattern: getInput('prereq-pattern'), + skipLabel: getInput('skip-label'), + failureMessage: getInput('failure-message'), + token: getInput('token'), + } +} + +function getInput(name) { + return process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '' +} + +async function listChangedFiles(payload, token) { + const owner = payload.repository.owner.login + const repo = payload.repository.name + const pullNumber = payload.pull_request.number + const filenames = [] + let page = 1 + + while (true) { + const url = new URL(`https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/files`) + url.searchParams.set('per_page', '100') + url.searchParams.set('page', String(page)) + + const response = await fetch(url, { + headers: getRequestHeaders(token), + }) + + if (!response.ok) { + throw new Error( + `Unable to list pull request files: received ${response.status} response with body: ${await response.text()}`, + ) + } + + const files = await response.json() + filenames.push(...files.map(file => file.filename)) + + if (files.length < 100) { + break + } + page += 1 + } + + return filenames +} + +function getRequestHeaders(token) { + const headers = { + Accept: 'application/vnd.github+json', + 'User-Agent': userAgent, + 'X-GitHub-Api-Version': apiVersion, + } + + if (token) { + headers.Authorization = ['Bearer', token].join(' ') + } + + return headers +} + +function anyFileMatches(filenames, patterns) { + return patterns + .split('\n') + .filter(Boolean) + .some(pattern => filenames.some(filename => matchesPattern(filename, pattern))) +} + +function matchesPattern(filename, pattern) { + return globToRegExp(pattern).test(filename) +} + +function globToRegExp(pattern) { + let source = '' + + for (let index = 0; index < pattern.length; index += 1) { + const character = pattern[index] + const nextCharacter = pattern[index + 1] + + if (character === '*' && nextCharacter === '*') { + source += '.*' + index += 1 + } else if (character === '*') { + source += '[^/]*' + } else if (character === '?') { + source += '[^/]' + } else { + source += escapeRegExp(character) + } + } + + return new RegExp(`^${source}$`) +} + +function escapeRegExp(value) { + return value.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') +} + +function formatFailureMessage(inputs) { + return inputs.failureMessage + .replaceAll('${prereq-pattern}', JSON.stringify(inputs.preReqPattern)) + .replaceAll('${file-pattern}', JSON.stringify(inputs.filePattern)) + .replaceAll('${skip-label}', JSON.stringify(inputs.skipLabel)) +} + +function info(message) { + process.stdout.write(`${message}\n`) +} + +function fail(message) { + process.stderr.write(`::error::${message}\n`) + process.exitCode = 1 +} diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index af7d138639d..a448439a32d 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -15,11 +15,15 @@ jobs: check-for-changeset: name: Check for changeset runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: 'Check for changeset' - uses: brettcannon/check-for-changed-files@v1 + uses: ./.github/actions/check-for-changed-files with: file-pattern: '.changeset/*.md' skip-label: 'skip changeset' failure-message: 'No changeset found. If these changes should not result in a new version, apply the ${skip-label} label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ' + token: ${{ github.token }} From 1c1a26f754b607fd3d0fa310d388553e8243f291 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 18:15:39 +0000 Subject: [PATCH 02/11] Fix local changeset action lint Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../actions/check-for-changed-files/index.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/actions/check-for-changed-files/index.js b/.github/actions/check-for-changed-files/index.js index db66075ffab..77e158f4cf5 100644 --- a/.github/actions/check-for-changed-files/index.js +++ b/.github/actions/check-for-changed-files/index.js @@ -1,14 +1,18 @@ -const fs = require('node:fs') - const apiVersion = '2022-11-28' const userAgent = 'primer-react-check-for-changed-files' -main().catch(error => { - fail(error.message) -}) +run() + +async function run() { + try { + await main() + } catch (error) { + fail(error.message) + } +} async function main() { - const payload = readEventPayload() + const payload = await readEventPayload() const inputs = readInputs() if (!payload || !payload.pull_request || !payload.repository || process.env.GITHUB_EVENT_NAME !== 'pull_request') { @@ -38,18 +42,19 @@ async function main() { fail(formatFailureMessage(inputs)) } -function readEventPayload() { +async function readEventPayload() { const eventPath = process.env.GITHUB_EVENT_PATH if (!eventPath) { return undefined } - return JSON.parse(fs.readFileSync(eventPath, 'utf8')) + const fs = await import('node:fs/promises') + return JSON.parse(await fs.readFile(eventPath, 'utf8')) } function readInputs() { return { filePattern: getInput('file-pattern'), - preReqPattern: getInput('prereq-pattern'), + preReqPattern: getInput('prereq-pattern') || '**', skipLabel: getInput('skip-label'), failureMessage: getInput('failure-message'), token: getInput('token'), From b8f968dc3c69a202cecc6fae364e1eb5503bbb4c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 18:20:43 +0000 Subject: [PATCH 03/11] Broaden glob regex escaping Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/actions/check-for-changed-files/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/check-for-changed-files/index.js b/.github/actions/check-for-changed-files/index.js index 77e158f4cf5..cee1407f1f8 100644 --- a/.github/actions/check-for-changed-files/index.js +++ b/.github/actions/check-for-changed-files/index.js @@ -147,7 +147,7 @@ function globToRegExp(pattern) { } function escapeRegExp(value) { - return value.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') + return value.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&') } function formatFailureMessage(inputs) { From 32c308c4ae34a41498c41ef09fc5ae09324ffda0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 18:24:35 +0000 Subject: [PATCH 04/11] Handle recursive glob patterns in local action Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/actions/check-for-changed-files/index.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/actions/check-for-changed-files/index.js b/.github/actions/check-for-changed-files/index.js index cee1407f1f8..4ddcabe2f1d 100644 --- a/.github/actions/check-for-changed-files/index.js +++ b/.github/actions/check-for-changed-files/index.js @@ -132,8 +132,13 @@ function globToRegExp(pattern) { const nextCharacter = pattern[index + 1] if (character === '*' && nextCharacter === '*') { - source += '.*' - index += 1 + if (pattern[index + 2] === '/') { + source += '(?:.*/)?' + index += 2 + } else { + source += '.*' + index += 1 + } } else if (character === '*') { source += '[^/]*' } else if (character === '?') { @@ -163,5 +168,5 @@ function info(message) { function fail(message) { process.stderr.write(`::error::${message}\n`) - process.exitCode = 1 + process.exit(1) } From ce994d69f9688e9ab43f22811e3881e81a1dcbfe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 20:31:19 +0000 Subject: [PATCH 05/11] Inline changeset check workflow Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .../check-for-changed-files/action.yml | 25 --- .../actions/check-for-changed-files/index.js | 172 ------------------ .github/workflows/check_for_changeset.yml | 28 ++- 3 files changed, 21 insertions(+), 204 deletions(-) delete mode 100644 .github/actions/check-for-changed-files/action.yml delete mode 100644 .github/actions/check-for-changed-files/index.js diff --git a/.github/actions/check-for-changed-files/action.yml b/.github/actions/check-for-changed-files/action.yml deleted file mode 100644 index 9faccfd7859..00000000000 --- a/.github/actions/check-for-changed-files/action.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: 'Check for Changed Files' -description: 'Require changed files in a pull request' -inputs: - file-pattern: - description: 'Glob pattern for changed file to check for' - required: true - prereq-pattern: - description: 'Glob pattern that guards whether the action will run' - required: false - default: '**' - skip-label: - description: 'Label to trigger skipping the check' - required: false - default: '' - failure-message: - description: 'String template used when the check fails' - required: false - default: 'the prerequisite file pattern ${prereq-pattern} matched changed files in the pull request, but the ${file-pattern} pattern did NOT and the ${skip-label} label is not set' - token: - description: 'GitHub token to use to list the pull request files' - required: false - default: '' -runs: - using: 'node20' - main: 'index.js' diff --git a/.github/actions/check-for-changed-files/index.js b/.github/actions/check-for-changed-files/index.js deleted file mode 100644 index 4ddcabe2f1d..00000000000 --- a/.github/actions/check-for-changed-files/index.js +++ /dev/null @@ -1,172 +0,0 @@ -const apiVersion = '2022-11-28' -const userAgent = 'primer-react-check-for-changed-files' - -run() - -async function run() { - try { - await main() - } catch (error) { - fail(error.message) - } -} - -async function main() { - const payload = await readEventPayload() - const inputs = readInputs() - - if (!payload || !payload.pull_request || !payload.repository || process.env.GITHUB_EVENT_NAME !== 'pull_request') { - info(`${JSON.stringify(process.env.GITHUB_EVENT_NAME)} is not a full 'pull_request' event; skipping`) - return - } - - const labels = payload.pull_request.labels.map(label => label.name) - if (inputs.skipLabel && labels.includes(inputs.skipLabel)) { - info(`the skip label ${JSON.stringify(inputs.skipLabel)} is set`) - return - } - - const filenames = await listChangedFiles(payload, inputs.token) - if (!anyFileMatches(filenames, inputs.preReqPattern)) { - info( - `the prerequisite ${JSON.stringify(inputs.preReqPattern)} file pattern did not match any changed files of the pull request`, - ) - return - } - - if (anyFileMatches(filenames, inputs.filePattern)) { - info(`the ${JSON.stringify(inputs.filePattern)} file pattern matched the changed files of the pull request`) - return - } - - fail(formatFailureMessage(inputs)) -} - -async function readEventPayload() { - const eventPath = process.env.GITHUB_EVENT_PATH - if (!eventPath) { - return undefined - } - const fs = await import('node:fs/promises') - return JSON.parse(await fs.readFile(eventPath, 'utf8')) -} - -function readInputs() { - return { - filePattern: getInput('file-pattern'), - preReqPattern: getInput('prereq-pattern') || '**', - skipLabel: getInput('skip-label'), - failureMessage: getInput('failure-message'), - token: getInput('token'), - } -} - -function getInput(name) { - return process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '' -} - -async function listChangedFiles(payload, token) { - const owner = payload.repository.owner.login - const repo = payload.repository.name - const pullNumber = payload.pull_request.number - const filenames = [] - let page = 1 - - while (true) { - const url = new URL(`https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/files`) - url.searchParams.set('per_page', '100') - url.searchParams.set('page', String(page)) - - const response = await fetch(url, { - headers: getRequestHeaders(token), - }) - - if (!response.ok) { - throw new Error( - `Unable to list pull request files: received ${response.status} response with body: ${await response.text()}`, - ) - } - - const files = await response.json() - filenames.push(...files.map(file => file.filename)) - - if (files.length < 100) { - break - } - page += 1 - } - - return filenames -} - -function getRequestHeaders(token) { - const headers = { - Accept: 'application/vnd.github+json', - 'User-Agent': userAgent, - 'X-GitHub-Api-Version': apiVersion, - } - - if (token) { - headers.Authorization = ['Bearer', token].join(' ') - } - - return headers -} - -function anyFileMatches(filenames, patterns) { - return patterns - .split('\n') - .filter(Boolean) - .some(pattern => filenames.some(filename => matchesPattern(filename, pattern))) -} - -function matchesPattern(filename, pattern) { - return globToRegExp(pattern).test(filename) -} - -function globToRegExp(pattern) { - let source = '' - - for (let index = 0; index < pattern.length; index += 1) { - const character = pattern[index] - const nextCharacter = pattern[index + 1] - - if (character === '*' && nextCharacter === '*') { - if (pattern[index + 2] === '/') { - source += '(?:.*/)?' - index += 2 - } else { - source += '.*' - index += 1 - } - } else if (character === '*') { - source += '[^/]*' - } else if (character === '?') { - source += '[^/]' - } else { - source += escapeRegExp(character) - } - } - - return new RegExp(`^${source}$`) -} - -function escapeRegExp(value) { - return value.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&') -} - -function formatFailureMessage(inputs) { - return inputs.failureMessage - .replaceAll('${prereq-pattern}', JSON.stringify(inputs.preReqPattern)) - .replaceAll('${file-pattern}', JSON.stringify(inputs.filePattern)) - .replaceAll('${skip-label}', JSON.stringify(inputs.skipLabel)) -} - -function info(message) { - process.stdout.write(`${message}\n`) -} - -function fail(message) { - process.stderr.write(`::error::${message}\n`) - process.exit(1) -} diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index a448439a32d..5c48ed4d6e7 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -19,11 +19,25 @@ jobs: contents: read pull-requests: read steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: 'Check for changeset' - uses: ./.github/actions/check-for-changed-files - with: - file-pattern: '.changeset/*.md' - skip-label: 'skip changeset' - failure-message: 'No changeset found. If these changes should not result in a new version, apply the ${skip-label} label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ' - token: ${{ github.token }} + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + SKIP_LABEL: 'skip changeset' + run: | + set -euo pipefail + + if jq -r '.pull_request.labels[].name' "$GITHUB_EVENT_PATH" | grep -Fxq "$SKIP_LABEL"; then + echo "the skip label \"$SKIP_LABEL\" is set" + exit 0 + fi + + changed_files="$(gh api --paginate "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/files" --jq '.[].filename')" + + if grep -Eq '^\.changeset/[^/]+\.md$' <<<"$changed_files"; then + echo 'the ".changeset/*.md" file pattern matched the changed files of the pull request' + exit 0 + fi + + echo "::error::No changeset found. If these changes should not result in a new version, apply the $SKIP_LABEL label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ" + exit 1 From 9d429df765bd57b89d1b565b04cdbc760f740c02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 20:33:55 +0000 Subject: [PATCH 06/11] Handle empty changeset label list Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/check_for_changeset.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index 5c48ed4d6e7..48d73dcaf8c 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -27,7 +27,7 @@ jobs: run: | set -euo pipefail - if jq -r '.pull_request.labels[].name' "$GITHUB_EVENT_PATH" | grep -Fxq "$SKIP_LABEL"; then + if jq -r '.pull_request.labels[].name // empty' "$GITHUB_EVENT_PATH" | grep -Fxq "$SKIP_LABEL"; then echo "the skip label \"$SKIP_LABEL\" is set" exit 0 fi From e81e492e39470d102fabcb49d37829555e3f43f8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 20:35:01 +0000 Subject: [PATCH 07/11] Refine inline changeset label handling Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/check_for_changeset.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index 48d73dcaf8c..b45746ad06f 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -27,7 +27,7 @@ jobs: run: | set -euo pipefail - if jq -r '.pull_request.labels[].name // empty' "$GITHUB_EVENT_PATH" | grep -Fxq "$SKIP_LABEL"; then + if jq -r '.pull_request.labels[]? | select(.name) | .name' "$GITHUB_EVENT_PATH" | grep -Fxq "$SKIP_LABEL"; then echo "the skip label \"$SKIP_LABEL\" is set" exit 0 fi @@ -39,5 +39,5 @@ jobs: exit 0 fi - echo "::error::No changeset found. If these changes should not result in a new version, apply the $SKIP_LABEL label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ" + echo "::error::No changeset found. If these changes should not result in a new version, apply the \"$SKIP_LABEL\" label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ" exit 1 From 731fe14846b59478deba8d2b4a82db2d621ae92c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 20:36:07 +0000 Subject: [PATCH 08/11] Simplify changeset label filter Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/check_for_changeset.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index b45746ad06f..8572d19ab57 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -27,15 +27,15 @@ jobs: run: | set -euo pipefail - if jq -r '.pull_request.labels[]? | select(.name) | .name' "$GITHUB_EVENT_PATH" | grep -Fxq "$SKIP_LABEL"; then - echo "the skip label \"$SKIP_LABEL\" is set" + if jq -r '.pull_request.labels[]?.name // empty' "$GITHUB_EVENT_PATH" | grep -Fxq "$SKIP_LABEL"; then + echo "The skip label \"$SKIP_LABEL\" is set" exit 0 fi changed_files="$(gh api --paginate "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/files" --jq '.[].filename')" if grep -Eq '^\.changeset/[^/]+\.md$' <<<"$changed_files"; then - echo 'the ".changeset/*.md" file pattern matched the changed files of the pull request' + echo 'The ".changeset/*.md" file pattern matched the changed files of the pull request' exit 0 fi From c58b337ca9e4d5b81ef1e394aaa4117d36645b7e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 21:36:25 +0000 Subject: [PATCH 09/11] Comment on missing changeset Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/check_for_changeset.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index 8572d19ab57..f13d15eb506 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -17,11 +17,13 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + issues: write pull-requests: read steps: - name: 'Check for changeset' env: GH_TOKEN: ${{ github.token }} + COMMENT_MARKER: '' PR_NUMBER: ${{ github.event.pull_request.number }} SKIP_LABEL: 'skip changeset' run: | @@ -39,5 +41,22 @@ jobs: exit 0 fi - echo "::error::No changeset found. If these changes should not result in a new version, apply the \"$SKIP_LABEL\" label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ" + failure_message="No changeset found. If these changes should not result in a new version, apply the \"$SKIP_LABEL\" label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ" + comment_body="$(cat </dev/null + echo "Updated existing changeset failure comment" + else + gh api -X POST "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" -f body="$comment_body" >/dev/null + echo "Created changeset failure comment" + fi + + echo "::error::$failure_message" exit 1 From b60a3a22f4e14997e32b8c90758a931dcdfc84c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 17:27:24 +0000 Subject: [PATCH 10/11] ci: fix check_for_changeset workflow - change pull-requests to write Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/check_for_changeset.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index f13d15eb506..f253c9aebfe 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -18,7 +18,7 @@ jobs: permissions: contents: read issues: write - pull-requests: read + pull-requests: write steps: - name: 'Check for changeset' env: From 12fdecbd89c99593a2042dda326b2feb110cfa79 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:51:56 +0000 Subject: [PATCH 11/11] ci: remove PR comment logic and tighten workflow permissions Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com> --- .github/workflows/check_for_changeset.yml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/workflows/check_for_changeset.yml b/.github/workflows/check_for_changeset.yml index f253c9aebfe..92ddb2f5c41 100644 --- a/.github/workflows/check_for_changeset.yml +++ b/.github/workflows/check_for_changeset.yml @@ -17,13 +17,11 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - issues: write - pull-requests: write + pull-requests: read steps: - name: 'Check for changeset' env: GH_TOKEN: ${{ github.token }} - COMMENT_MARKER: '' PR_NUMBER: ${{ github.event.pull_request.number }} SKIP_LABEL: 'skip changeset' run: | @@ -42,21 +40,5 @@ jobs: fi failure_message="No changeset found. If these changes should not result in a new version, apply the \"$SKIP_LABEL\" label to this pull request. If these changes should result in a version bump, please add a changeset https://git.io/J6QvQ" - comment_body="$(cat </dev/null - echo "Updated existing changeset failure comment" - else - gh api -X POST "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" -f body="$comment_body" >/dev/null - echo "Created changeset failure comment" - fi - echo "::error::$failure_message" exit 1