From 72d8de82227f612aa28cb7313ed14bec5c2599b3 Mon Sep 17 00:00:00 2001 From: laim2003 Date: Tue, 13 Oct 2026 13:07:40 +0200 Subject: [PATCH 1/8] #2644: Added PR label check workflow Signed-off-by: laim2003 --- .github/workflows/check-pr-labels.yml | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/check-pr-labels.yml diff --git a/.github/workflows/check-pr-labels.yml b/.github/workflows/check-pr-labels.yml new file mode 100644 index 0000000000..94ec654436 --- /dev/null +++ b/.github/workflows/check-pr-labels.yml @@ -0,0 +1,41 @@ +name: Check PR Labels + +# Fails (red check) while a pull request has no labels and turns green as soon as at +# least one label is assigned. It runs on the events that can change a PR's labels so +# the check re-evaluates immediately when a label is added or removed. No write access: +# this only reads the PR and reports a failure, so pull_request (not pull_request_target) +# is the correct trigger. + +on: + pull_request: + types: [opened, reopened, labeled, unlabeled] + +permissions: + pull-requests: read + +jobs: + check-labels: + runs-on: ubuntu-latest + steps: + - name: Verify the PR has at least one label + uses: actions/github-script@v7 + with: + script: | + const core = require('@actions/core'); + + // Fetch the PR fresh so the label state is authoritative for this run. + const pr = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number + }); + + const labels = pr.data.labels.map(label => label.name); + if (labels.length > 0) { + console.log(`PR has ${labels.length} label(s): ${labels.join(', ')}.`); + } else { + core.setFailed( + 'This pull request has no labels assigned. Add at least one label to the PR ' + + '(e.g. "bug", "enhancement", "documentation") to make this check pass.' + ); + } From 7b9db01bc0af1bda813dc380b2bc34e2e980fc89 Mon Sep 17 00:00:00 2001 From: laim2003 Date: Tue, 13 Oct 2026 13:11:50 +0200 Subject: [PATCH 2/8] #2644: fixed script error Signed-off-by: laim2003 --- .github/workflows/check-pr-labels.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/check-pr-labels.yml b/.github/workflows/check-pr-labels.yml index 94ec654436..5df92544c1 100644 --- a/.github/workflows/check-pr-labels.yml +++ b/.github/workflows/check-pr-labels.yml @@ -21,8 +21,6 @@ jobs: uses: actions/github-script@v7 with: script: | - const core = require('@actions/core'); - // Fetch the PR fresh so the label state is authoritative for this run. const pr = await github.rest.pulls.get({ owner: context.repo.owner, From 0a9bcc8de0879af6b8ccc2b43dff0fd89ae73e58 Mon Sep 17 00:00:00 2001 From: laim2003 Date: Tue, 13 Oct 2026 13:20:00 +0200 Subject: [PATCH 3/8] #2644: fixed check triggers Signed-off-by: laim2003 --- .github/workflows/check-pr-labels.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-pr-labels.yml b/.github/workflows/check-pr-labels.yml index 5df92544c1..672a7d7126 100644 --- a/.github/workflows/check-pr-labels.yml +++ b/.github/workflows/check-pr-labels.yml @@ -1,14 +1,15 @@ name: Check PR Labels # Fails (red check) while a pull request has no labels and turns green as soon as at -# least one label is assigned. It runs on the events that can change a PR's labels so -# the check re-evaluates immediately when a label is added or removed. No write access: -# this only reads the PR and reports a failure, so pull_request (not pull_request_target) +# least one label is assigned. It runs on the events that can change a PR's labels or +# its head commit (synchronize = author pushed new commits), so the check re-evaluates +# immediately and is never missing on a freshly pushed commit. No write access: this +# only reads the PR and reports a failure, so pull_request (not pull_request_target) # is the correct trigger. on: pull_request: - types: [opened, reopened, labeled, unlabeled] + types: [opened, reopened, synchronize, labeled, unlabeled] permissions: pull-requests: read From 083b0fc3b5a07ff22ed2b6b1601de07465da35d2 Mon Sep 17 00:00:00 2001 From: laim2003 Date: Tue, 13 Oct 2026 13:43:57 +0200 Subject: [PATCH 4/8] #2647: Add check for either internal label or Changelog entry Signed-off-by: laim2003 --- .github/workflows/check-pr-labels.yml | 63 ++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check-pr-labels.yml b/.github/workflows/check-pr-labels.yml index 672a7d7126..ce98e978ef 100644 --- a/.github/workflows/check-pr-labels.yml +++ b/.github/workflows/check-pr-labels.yml @@ -1,11 +1,16 @@ -name: Check PR Labels +name: Check PR Labels & Changelog # Fails (red check) while a pull request has no labels and turns green as soon as at -# least one label is assigned. It runs on the events that can change a PR's labels or -# its head commit (synchronize = author pushed new commits), so the check re-evaluates -# immediately and is never missing on a freshly pushed commit. No write access: this -# only reads the PR and reports a failure, so pull_request (not pull_request_target) -# is the correct trigger. +# least one label is assigned. It then applies the changelog policy: a PR is exempt +# when it is labelled "internal" (no user-facing change), otherwise it must add at +# least one line to CHANGELOG.adoc. The changelog step is skipped while the label +# check fails, so an unlabeled PR first just has to add a label. It runs on the events +# that can change a PR's labels or its head commit (synchronize = author pushed new +# commits), so the check re-evaluates immediately and is never missing on a freshly +# pushed commit. No write access: this only reads the PR and reports a failure, so +# pull_request (not pull_request_target) is the correct trigger. The changelog policy +# comes from documentation/contributing/DoD.adoc: the CHANGELOG shall only reflect +# public changes relevant for end-users. on: pull_request: @@ -15,7 +20,7 @@ permissions: pull-requests: read jobs: - check-labels: + check-labels-and-changelog: runs-on: ubuntu-latest steps: - name: Verify the PR has at least one label @@ -38,3 +43,47 @@ jobs: + '(e.g. "bug", "enhancement", "documentation") to make this check pass.' ); } + + - name: Verify internal label or a new CHANGELOG.adoc line + # Only meaningful once the PR has labels; an unlabeled PR already failed the + # step above and has to add a label first. + if: success() + uses: actions/github-script@v7 + with: + script: | + const INTERNAL_LABEL = 'internal'; + const CHANGELOG = 'CHANGELOG.adoc'; + const prNumber = context.payload.pull_request.number; + + // Fetch the PR fresh so the label state is authoritative for this run. + const pr = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber + }); + + const labels = pr.data.labels.map(label => label.name); + if (labels.includes(INTERNAL_LABEL)) { + console.log(`PR is labelled "${INTERNAL_LABEL}" - no ${CHANGELOG} entry required.`); + return; + } + + // Not internal: the PR must add a line to CHANGELOG.adoc. Paginate in case a + // PR changes more than 100 files. "additions" counts new lines in that file. + const files = await github.paginate( + github.rest.pulls.listFiles, + { owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber, per_page: 100 } + ); + const changelog = files.find(file => file.filename === CHANGELOG); + const addedLines = changelog ? changelog.additions : 0; + + if (addedLines > 0) { + console.log(`${CHANGELOG} has ${addedLines} added line(s).`); + } else { + core.setFailed( + `This PR is not labelled "${INTERNAL_LABEL}" but adds no line to ${CHANGELOG}. ` + + `Please document this user-facing change by adding a line to ${CHANGELOG} under the next ` + + `open release, or add the "${INTERNAL_LABEL}" label if the change has no user-facing ` + + `impact. See documentation/contributing/DoD.adoc.` + ); + } From 675bcc34d96d0bdc80065b04b301e1452a1515fb Mon Sep 17 00:00:00 2001 From: laim2003 Date: Tue, 13 Oct 2026 13:52:57 +0200 Subject: [PATCH 5/8] #2647: Add check for either internal label or Changelog entry Signed-off-by: laim2003 --- .github/workflows/check-pr-labels.yml | 47 +++++++++++++++------------ CHANGELOG.adoc | 1 + 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/.github/workflows/check-pr-labels.yml b/.github/workflows/check-pr-labels.yml index ce98e978ef..8ed24a2ef5 100644 --- a/.github/workflows/check-pr-labels.yml +++ b/.github/workflows/check-pr-labels.yml @@ -1,16 +1,17 @@ name: Check PR Labels & Changelog # Fails (red check) while a pull request has no labels and turns green as soon as at -# least one label is assigned. It then applies the changelog policy: a PR is exempt -# when it is labelled "internal" (no user-facing change), otherwise it must add at -# least one line to CHANGELOG.adoc. The changelog step is skipped while the label -# check fails, so an unlabeled PR first just has to add a label. It runs on the events -# that can change a PR's labels or its head commit (synchronize = author pushed new -# commits), so the check re-evaluates immediately and is never missing on a freshly -# pushed commit. No write access: this only reads the PR and reports a failure, so -# pull_request (not pull_request_target) is the correct trigger. The changelog policy -# comes from documentation/contributing/DoD.adoc: the CHANGELOG shall only reflect -# public changes relevant for end-users. +# least one label is assigned. It then applies the changelog policy, which makes the +# "internal" label and a new CHANGELOG.adoc line mutually exclusive: an internal +# (no user-facing impact) PR must not carry a changelog entry, and a non-internal PR +# must add one. The changelog step is skipped while the label check fails, so an +# unlabeled PR first just has to add a label. It runs on the events that can change +# a PR's labels or its head commit (synchronize = author pushed new commits), so the +# check re-evaluates immediately and is never missing on a freshly pushed commit. No +# write access: this only reads the PR and reports a failure, so pull_request (not +# pull_request_target) is the correct trigger. The changelog policy comes from +# documentation/contributing/DoD.adoc: the CHANGELOG shall only reflect public +# changes relevant for end-users. on: pull_request: @@ -44,7 +45,7 @@ jobs: ); } - - name: Verify internal label or a new CHANGELOG.adoc line + - name: Verify internal label and CHANGELOG.adoc entry are mutually exclusive # Only meaningful once the PR has labels; an unlabeled PR already failed the # step above and has to add a label first. if: success() @@ -63,13 +64,10 @@ jobs: }); const labels = pr.data.labels.map(label => label.name); - if (labels.includes(INTERNAL_LABEL)) { - console.log(`PR is labelled "${INTERNAL_LABEL}" - no ${CHANGELOG} entry required.`); - return; - } + const isInternal = labels.includes(INTERNAL_LABEL); - // Not internal: the PR must add a line to CHANGELOG.adoc. Paginate in case a - // PR changes more than 100 files. "additions" counts new lines in that file. + // Paginate in case a PR changes more than 100 files. "additions" counts + // new lines in that file. const files = await github.paginate( github.rest.pulls.listFiles, { owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber, per_page: 100 } @@ -77,13 +75,22 @@ jobs: const changelog = files.find(file => file.filename === CHANGELOG); const addedLines = changelog ? changelog.additions : 0; - if (addedLines > 0) { - console.log(`${CHANGELOG} has ${addedLines} added line(s).`); - } else { + if (isInternal && addedLines > 0) { + core.setFailed( + `This PR has the "${INTERNAL_LABEL}" label but adds ${addedLines} line(s) to ${CHANGELOG}. ` + + `Internal changes have no user-facing impact and should not be documented. ` + + `Please remove the entry from ${CHANGELOG}, or remove the "${INTERNAL_LABEL}" ` + + `label if the change is user-facing. See documentation/contributing/DoD.adoc.` + ); + } else if (!isInternal && addedLines === 0) { core.setFailed( `This PR is not labelled "${INTERNAL_LABEL}" but adds no line to ${CHANGELOG}. ` + `Please document this user-facing change by adding a line to ${CHANGELOG} under the next ` + `open release, or add the "${INTERNAL_LABEL}" label if the change has no user-facing ` + `impact. See documentation/contributing/DoD.adoc.` ); + } else { + console.log(isInternal + ? `PR is labelled "${INTERNAL_LABEL}" and adds no line to ${CHANGELOG}.` + : `${CHANGELOG} has ${addedLines} added line(s).`); } diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index caf62630ea..0628e8a624 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -13,6 +13,7 @@ Release with new features and bugfixes: * https://github.com/devonfw/IDEasy/issues/2381[#2381]: Make node and npm pristine versioned tools with per-project npm global prefix * https://github.com/devonfw/IDEasy/issues/2607[#2607]: Align tool help for corepack * https://github.com/devonfw/IDEasy/issues/2322[#2322]: Use a consistent IDEasy icon across all operating systems +* https://github.com/devonfw/IDEasy/issues/2647[#2647]: Added a check for changelog entries for new pull requests The full list of changes for this release can be found in https://github.com/devonfw/IDEasy/milestone/51?closed=1[milestone 2026.10.001]. From 972e5cb9698ba7a6ed30105309c9a3399ffaf259 Mon Sep 17 00:00:00 2001 From: laim2003 Date: Tue, 13 Oct 2026 13:55:15 +0200 Subject: [PATCH 6/8] #2647: removed test changelog entry Signed-off-by: laim2003 --- CHANGELOG.adoc | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0628e8a624..caf62630ea 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -13,7 +13,6 @@ Release with new features and bugfixes: * https://github.com/devonfw/IDEasy/issues/2381[#2381]: Make node and npm pristine versioned tools with per-project npm global prefix * https://github.com/devonfw/IDEasy/issues/2607[#2607]: Align tool help for corepack * https://github.com/devonfw/IDEasy/issues/2322[#2322]: Use a consistent IDEasy icon across all operating systems -* https://github.com/devonfw/IDEasy/issues/2647[#2647]: Added a check for changelog entries for new pull requests The full list of changes for this release can be found in https://github.com/devonfw/IDEasy/milestone/51?closed=1[milestone 2026.10.001]. From f12e7619657df181cf98bf9097c0f1c8db795351 Mon Sep 17 00:00:00 2001 From: laim2003 Date: Thu, 15 Oct 2026 17:18:23 +0200 Subject: [PATCH 7/8] #2647: updated workflow explanation Signed-off-by: laim2003 --- .github/workflows/check-pr-labels.yml | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/.github/workflows/check-pr-labels.yml b/.github/workflows/check-pr-labels.yml index 8ed24a2ef5..4bde84ca71 100644 --- a/.github/workflows/check-pr-labels.yml +++ b/.github/workflows/check-pr-labels.yml @@ -1,21 +1,20 @@ name: Check PR Labels & Changelog -# Fails (red check) while a pull request has no labels and turns green as soon as at -# least one label is assigned. It then applies the changelog policy, which makes the -# "internal" label and a new CHANGELOG.adoc line mutually exclusive: an internal -# (no user-facing impact) PR must not carry a changelog entry, and a non-internal PR -# must add one. The changelog step is skipped while the label check fails, so an -# unlabeled PR first just has to add a label. It runs on the events that can change -# a PR's labels or its head commit (synchronize = author pushed new commits), so the -# check re-evaluates immediately and is never missing on a freshly pushed commit. No -# write access: this only reads the PR and reports a failure, so pull_request (not -# pull_request_target) is the correct trigger. The changelog policy comes from -# documentation/contributing/DoD.adoc: the CHANGELOG shall only reflect public -# changes relevant for end-users. +# - Fails while a pull request has no labels. +# - Passes as soon as at least one label is assigned. +# - Enforces the changelog policy: +# - "internal" PR: must not add a CHANGELOG.adoc entry. +# - Non-"internal" PR: must add a CHANGELOG.adoc entry. +# - Skips the changelog check until the PR has at least one label. +# - Re-runs when: +# - PR labels change. +# - New commits are pushed (synchronize). +# - Based on documentation/contributing/DoD.adoc: the changelog should contain only +# public, end-user-relevant changes. on: pull_request: - types: [opened, reopened, synchronize, labeled, unlabeled] + types: [ opened, reopened, synchronize, labeled, unlabeled ] permissions: pull-requests: read From 35113786a9b9f29577cd96d9ec484f00a8ad4a58 Mon Sep 17 00:00:00 2001 From: laim2003 Date: Thu, 22 Oct 2026 16:56:05 +0200 Subject: [PATCH 8/8] #2649: updated dependabot.yml to fit new label check Signed-off-by: laim2003 --- .github/dependabot.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9c837ba1fd..bbf71eb29e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,6 @@ updates: directory: "/" schedule: interval: "weekly" + labels: + - "dependencies" + - "internal"