Copilot commented on code in PR #419: URL: https://github.com/apache/logging-parent/pull/419#discussion_r3094151067
########## .github/workflows/analyze-dependabot-reusable.yaml: ########## @@ -0,0 +1,59 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Analyze PR + +on: + workflow_call: { } + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + +jobs: + + analyze-pull-request: + # Defense-in-depth (in case the caller forgets): + # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR; + # `github.event.pull_request.user.login` skips PRs not opened by Dependabot. + if: ${{ + github.actor == 'dependabot[bot]' + && github.event.pull_request.user.login == 'dependabot[bot]' + }} + runs-on: ubuntu-latest + + steps: + + - name: Fetch Dependabot metadata + id: dependabot + uses: dependabot/fetch-metadata@ffa630c65fa7e0ecfa0625b5ceda64399aea1b36 # 3.0.0 + with: + github-token: ${{ github.token }} + + # Creates the data required by the `process-dependabot-reusable` workflow as a JSON file. + - name: Create artifact + shell: bash + env: + UPDATED_DEPENDENCIES: ${{ steps.dependabot.outputs.updated-dependencies-json }} + run: | + echo "$UPDATED_DEPENDENCIES" > updated_dependencies.json + + - name: Upload artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # 7.0.1 Review Comment: This workflow pins `actions/upload-artifact` to a different commit than the rest of the repo (most workflows use `actions/upload-artifact@ea165f8d... # 4.6.2`, e.g. `.github/workflows/build-reusable.yaml:143`). Aligning on a single vetted pin/version across workflows makes supply-chain auditing and maintenance easier. ```suggestion uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 ``` ########## .github/workflows/process-dependabot-reusable.yaml: ########## @@ -0,0 +1,142 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Process PR + +on: + workflow_call: + inputs: + changelog-path: + description: The path to the changelog directory (e.g. `src/changelog/.2.x.x`) + required: true + type: string + secrets: + RECURSIVE_TOKEN: + description: "A PAT with `contents: write` permission to push changes and trigger the next workflow run" + required: true + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + +jobs: + + generate-changelog: + # Defense-in-depth (in case the caller forgets): + # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR; + # `github.event.workflow_run.conclusion` only runs after a successful analysis workflow. + if: ${{ + github.actor == 'dependabot[bot]' + && github.event.workflow_run.conclusion == 'success' + }} + runs-on: ubuntu-latest + permissions: + # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR + # This requires the following two permissions: + contents: write + pull-requests: write + + steps: + + - name: Get pull request metadata + id: pr + env: + # Reference of the payload: https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_run + # + # The structure of `pull_requests` is not documented, so we'll dump it for debugging purposes. + PULL_REQUESTS: ${{ toJSON(github.event.workflow_run.pull_requests) }} + run: | + # Print payload for debugging + jq <<< "$PULL_REQUESTS" + echo "id=$(echo "$PULL_REQUESTS" | jq -r '.[0].number')" >> "$GITHUB_OUTPUT" + echo "head-ref=$(echo "$PULL_REQUESTS" | jq -r '.[0].head.ref')" >> "$GITHUB_OUTPUT" + + - name: Fetch Dependabot metadata + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # 8.0.1 + with: + github-token: ${{ github.token }} + name: dependabot-metadata + path: ${{ runner.temp }} + run-id: ${{ github.event.workflow_run.id }} + + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 + with: + ref: ${{ steps.pr.outputs.head-ref }} + token: ${{ secrets.RECURSIVE_TOKEN }} + + - name: Create changelog entries + shell: bash + env: + PR_ID: ${{ steps.pr.outputs.id }} + PR_URL: ${{ github.server_url }}/${{ github.repository }}/pull/${{ steps.pr.outputs.id }} + CHANGELOG_PATH: ${{ inputs.changelog-path }} + UPDATED_DEPENDENCIES: ${{ runner.temp }}/updated_dependencies.json + run: | + # Escapes special XML characters in a string + xml_escape() { sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g'; } + + # Generates the content of a changelog entry + function generate_changelog_entry() { + local dependency="$1" + local issue_id=$(xml_escape <<< "$PR_ID") + local issue_link=$(xml_escape <<< "$PR_URL") + local dependency_name=$(echo "$dependency" | jq -r '.dependencyName' | xml_escape) + local new_version=$(echo "$dependency" | jq -r '.newVersion' | xml_escape) + cat << CHANGELOG_ENTRY + <?xml version="1.0" encoding="UTF-8"?> + <entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="https://logging.apache.org/xml/ns" + xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd" + type="updated"> + <issue id="$issue_id" link="$issue_link"/> + <description format="asciidoc">Update \`$dependency_name\` to version \`$new_version\`</description> + </entry> + CHANGELOG_ENTRY + } + + # Ensure the changelog directory exists + mkdir -p "$CHANGELOG_PATH" + cd "$CHANGELOG_PATH" + + # Generate the changelog entries for each updated dependency + cat "$UPDATED_DEPENDENCIES" | jq --compact-output '.[]' | while read -r dependency; do + # Extract the dependency name and version + dependency_name=$(echo "$dependency" | jq -r '.dependencyName') + changelog_file_name=$(echo "update_${dependency_name,,}.xml" | sed -r -e 's/[^a-z0-9.-]/_/g' -e 's/_+/_/g') + generate_changelog_entry "$dependency" > "$changelog_file_name" + done + + - name: Add & commit changes + shell: bash + env: + CHANGELOG_PATH: ${{ inputs.changelog-path }} + PR_ID: ${{ steps.pr.outputs.id }} + run: | + git add "$CHANGELOG_PATH" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git commit -m "Generate changelog entries for #$PR_ID" + git push origin Review Comment: `git commit` will fail the job when there are no staged changes (e.g., reruns or when files already exist). Also, `git push origin` relies on upstream configuration. Consider guarding the commit with a staged-diff check (skip if clean) and pushing explicitly to the PR head ref to make the behavior deterministic. ```suggestion HEAD_REF: ${{ steps.pr.outputs.head-ref }} run: | git add "$CHANGELOG_PATH" git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" if git diff --cached --quiet; then echo "No changelog changes to commit." else git commit -m "Generate changelog entries for #$PR_ID" git push origin "HEAD:${HEAD_REF}" fi ``` ########## src/site/antora/modules/ROOT/examples/process-dependabot.yaml: ########## @@ -0,0 +1,50 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: "Dependabot Process PR" + +on: + workflow_run: + workflows: + - "Dependabot Analyze PR" + types: + - completed + +permissions: { } + +jobs: + +# tag::process-dependabot[] + process-dependabot: + # Skip this workflow on commits not pushed by Dependabot + if: ${{ + github.repository == 'apache/logging-parent' + && github.actor == 'dependabot[bot]' + && github.event.workflow_run.conclusion == 'success' + }} + uses: apache/logging-parent/.github/workflows/process-dependabot-reusable.yaml@rel/{project-version} + permissions: + # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR + # This requires the following two permissions: Review Comment: This caller workflow grants only `contents: write` and `pull-requests: write`. Since the reusable `process-dependabot` workflow downloads an artifact from another workflow run, the caller likely also needs to grant `actions: read` (token permissions in a called workflow are capped by the caller). ```suggestion # and to allow the reusable workflow to download artifacts from another workflow run. actions: read ``` ########## src/site/antora/modules/ROOT/pages/workflows.adoc: ########## @@ -104,10 +104,64 @@ To verify the reproducibility of a release, you can use: include::example$build.yaml[tag=verify-reproducibility-release,indent=0] ---- -[#merge-dependabot] -== {project-github-url}/blob/main/.github/workflows/merge-dependabot-reusable.yaml[`merge-dependabot-reusable.yaml`] +[#analyze-dependabot] +== {project-github-url}/blob/main/.github/workflows/analyze-dependabot-reusable.yaml[`analyze-dependabot-reusable.yaml`] -Merges Dependabot PRs along with changelog entries. +Analyzes Dependabot pull requests to collect detailed information about updated dependencies. +Stores the results in the `dependabot-metadata` artifact, +which is later consumed by the <<process-dependabot>> workflow to automate changelog generation and PR processing. + Review Comment: This change removes/replaces the `merge-dependabot` section (anchor `[#merge-dependabot]`), but `workflows.adoc` still references `<<merge-dependabot>>` in the workflow list near the top of the page. Please update the list (and any other cross-references) to point to the new `analyze-dependabot` / `process-dependabot` sections so the docs don't contain broken links. ########## .github/workflows/process-dependabot-reusable.yaml: ########## @@ -0,0 +1,142 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Process PR + +on: + workflow_call: + inputs: + changelog-path: + description: The path to the changelog directory (e.g. `src/changelog/.2.x.x`) + required: true + type: string + secrets: + RECURSIVE_TOKEN: + description: "A PAT with `contents: write` permission to push changes and trigger the next workflow run" + required: true + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + +jobs: + + generate-changelog: + # Defense-in-depth (in case the caller forgets): + # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR; + # `github.event.workflow_run.conclusion` only runs after a successful analysis workflow. + if: ${{ + github.actor == 'dependabot[bot]' + && github.event.workflow_run.conclusion == 'success' + }} + runs-on: ubuntu-latest + permissions: + # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR + # This requires the following two permissions: Review Comment: The job downloads an artifact from a different workflow run (`actions/download-artifact` with `run-id:`). That typically requires `actions: read` on the `GITHUB_TOKEN`, but the job only grants `contents: write` and `pull-requests: write`. Please add the minimal `actions: read` permission so artifact download works reliably. ```suggestion # The default GITHUB_TOKEN is used both to download an artifact from the # triggering workflow run and to enable the "auto-merge" on the PR. actions: read ``` ########## .github/workflows/analyze-dependabot-reusable.yaml: ########## @@ -0,0 +1,59 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Analyze PR + +on: + workflow_call: { } + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + +jobs: + + analyze-pull-request: + # Defense-in-depth (in case the caller forgets): + # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR; + # `github.event.pull_request.user.login` skips PRs not opened by Dependabot. + if: ${{ + github.actor == 'dependabot[bot]' + && github.event.pull_request.user.login == 'dependabot[bot]' + }} + runs-on: ubuntu-latest + + steps: + + - name: Fetch Dependabot metadata + id: dependabot + uses: dependabot/fetch-metadata@ffa630c65fa7e0ecfa0625b5ceda64399aea1b36 # 3.0.0 + with: + github-token: ${{ github.token }} + Review Comment: `dependabot/fetch-metadata` is invoked with `github-token: ${{ github.token }}`, but with the current `permissions: { }` the token may not be able to read PR metadata. Please ensure the job/workflow grants the required read permissions so this step can reliably access the GitHub API. ########## .github/workflows/process-dependabot-reusable.yaml: ########## @@ -0,0 +1,142 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Process PR + +on: + workflow_call: + inputs: + changelog-path: + description: The path to the changelog directory (e.g. `src/changelog/.2.x.x`) + required: true + type: string + secrets: + RECURSIVE_TOKEN: + description: "A PAT with `contents: write` permission to push changes and trigger the next workflow run" + required: true + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + +jobs: + + generate-changelog: + # Defense-in-depth (in case the caller forgets): + # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR; + # `github.event.workflow_run.conclusion` only runs after a successful analysis workflow. + if: ${{ + github.actor == 'dependabot[bot]' + && github.event.workflow_run.conclusion == 'success' + }} + runs-on: ubuntu-latest + permissions: + # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR + # This requires the following two permissions: + contents: write + pull-requests: write + + steps: + + - name: Get pull request metadata + id: pr + env: + # Reference of the payload: https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_run + # + # The structure of `pull_requests` is not documented, so we'll dump it for debugging purposes. + PULL_REQUESTS: ${{ toJSON(github.event.workflow_run.pull_requests) }} + run: | + # Print payload for debugging + jq <<< "$PULL_REQUESTS" + echo "id=$(echo "$PULL_REQUESTS" | jq -r '.[0].number')" >> "$GITHUB_OUTPUT" + echo "head-ref=$(echo "$PULL_REQUESTS" | jq -r '.[0].head.ref')" >> "$GITHUB_OUTPUT" + + - name: Fetch Dependabot metadata + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # 8.0.1 + with: + github-token: ${{ github.token }} + name: dependabot-metadata + path: ${{ runner.temp }} + run-id: ${{ github.event.workflow_run.id }} + + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 Review Comment: `actions/checkout` is pinned to a different commit/version than the rest of the repository (most workflows use `actions/checkout@11bd7190... # 4.2.2`). For consistency and easier security auditing, consider using the same vetted pin across workflows unless there's a specific need for a different version. ```suggestion uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 ``` ########## .github/workflows/analyze-dependabot-reusable.yaml: ########## @@ -0,0 +1,59 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Analyze PR + +on: + workflow_call: { } + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + Review Comment: This reusable workflow sets `permissions: { }`, which makes `GITHUB_TOKEN` permissionless. Because the workflow uses `github.token` later, it should explicitly grant the minimal read permissions it needs (typically `pull-requests: read` and `contents: read`) at the workflow or job level. ########## .github/workflows/process-dependabot-reusable.yaml: ########## @@ -0,0 +1,142 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Process PR + +on: + workflow_call: + inputs: + changelog-path: + description: The path to the changelog directory (e.g. `src/changelog/.2.x.x`) + required: true + type: string + secrets: + RECURSIVE_TOKEN: + description: "A PAT with `contents: write` permission to push changes and trigger the next workflow run" + required: true + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + +jobs: + + generate-changelog: + # Defense-in-depth (in case the caller forgets): + # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR; + # `github.event.workflow_run.conclusion` only runs after a successful analysis workflow. + if: ${{ + github.actor == 'dependabot[bot]' + && github.event.workflow_run.conclusion == 'success' + }} + runs-on: ubuntu-latest + permissions: + # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR + # This requires the following two permissions: + contents: write + pull-requests: write + + steps: + + - name: Get pull request metadata + id: pr + env: + # Reference of the payload: https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_run + # + # The structure of `pull_requests` is not documented, so we'll dump it for debugging purposes. + PULL_REQUESTS: ${{ toJSON(github.event.workflow_run.pull_requests) }} + run: | + # Print payload for debugging + jq <<< "$PULL_REQUESTS" + echo "id=$(echo "$PULL_REQUESTS" | jq -r '.[0].number')" >> "$GITHUB_OUTPUT" + echo "head-ref=$(echo "$PULL_REQUESTS" | jq -r '.[0].head.ref')" >> "$GITHUB_OUTPUT" + + - name: Fetch Dependabot metadata + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # 8.0.1 + with: + github-token: ${{ github.token }} + name: dependabot-metadata + path: ${{ runner.temp }} + run-id: ${{ github.event.workflow_run.id }} + + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 + with: + ref: ${{ steps.pr.outputs.head-ref }} + token: ${{ secrets.RECURSIVE_TOKEN }} + + - name: Create changelog entries + shell: bash + env: + PR_ID: ${{ steps.pr.outputs.id }} + PR_URL: ${{ github.server_url }}/${{ github.repository }}/pull/${{ steps.pr.outputs.id }} + CHANGELOG_PATH: ${{ inputs.changelog-path }} + UPDATED_DEPENDENCIES: ${{ runner.temp }}/updated_dependencies.json + run: | + # Escapes special XML characters in a string + xml_escape() { sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g'; } + + # Generates the content of a changelog entry + function generate_changelog_entry() { + local dependency="$1" + local issue_id=$(xml_escape <<< "$PR_ID") + local issue_link=$(xml_escape <<< "$PR_URL") + local dependency_name=$(echo "$dependency" | jq -r '.dependencyName' | xml_escape) + local new_version=$(echo "$dependency" | jq -r '.newVersion' | xml_escape) + cat << CHANGELOG_ENTRY + <?xml version="1.0" encoding="UTF-8"?> + <entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="https://logging.apache.org/xml/ns" + xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd" + type="updated"> + <issue id="$issue_id" link="$issue_link"/> + <description format="asciidoc">Update \`$dependency_name\` to version \`$new_version\`</description> + </entry> + CHANGELOG_ENTRY + } + + # Ensure the changelog directory exists + mkdir -p "$CHANGELOG_PATH" + cd "$CHANGELOG_PATH" + + # Generate the changelog entries for each updated dependency + cat "$UPDATED_DEPENDENCIES" | jq --compact-output '.[]' | while read -r dependency; do + # Extract the dependency name and version + dependency_name=$(echo "$dependency" | jq -r '.dependencyName') + changelog_file_name=$(echo "update_${dependency_name,,}.xml" | sed -r -e 's/[^a-z0-9.-]/_/g' -e 's/_+/_/g') + generate_changelog_entry "$dependency" > "$changelog_file_name" + done Review Comment: Changelog filenames are derived from a sanitized `dependencyName` only. Different dependency names can sanitize to the same filename (e.g., `foo/bar` vs `foo-bar`), which would cause one entry to overwrite another in multi-dependency PRs. Consider incorporating an additional unique field (like `dependencyName` plus ecosystem / directory) or detecting collisions and failing with a clear error. ```suggestion declare -A generated_changelog_files=() while read -r dependency; do # Extract the dependency name and version dependency_name=$(echo "$dependency" | jq -r '.dependencyName') changelog_file_name=$(echo "update_${dependency_name,,}.xml" | sed -r -e 's/[^a-z0-9.-]/_/g' -e 's/_+/_/g') if [[ -n "${generated_changelog_files[$changelog_file_name]+x}" ]] && [[ "${generated_changelog_files[$changelog_file_name]}" != "$dependency_name" ]]; then echo "::error title=Duplicate changelog filename::Dependencies '${generated_changelog_files[$changelog_file_name]}' and '$dependency_name' both map to '$changelog_file_name' after sanitization. Update the filename generation to include an additional unique field." exit 1 fi generated_changelog_files["$changelog_file_name"]="$dependency_name" generate_changelog_entry "$dependency" > "$changelog_file_name" done < <(jq --compact-output '.[]' "$UPDATED_DEPENDENCIES") ``` ########## .github/workflows/process-dependabot-reusable.yaml: ########## @@ -0,0 +1,142 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Dependabot Process PR + +on: + workflow_call: + inputs: + changelog-path: + description: The path to the changelog directory (e.g. `src/changelog/.2.x.x`) + required: true + type: string + secrets: + RECURSIVE_TOKEN: + description: "A PAT with `contents: write` permission to push changes and trigger the next workflow run" + required: true + +# Explicitly drop all permissions inherited from the caller for security. +# Reference: https://docs.github.com/en/actions/sharing-automations/reusing-workflows#access-and-permissions +permissions: { } + +jobs: + + generate-changelog: + # Defense-in-depth (in case the caller forgets): + # `github.actor` prevents recursive calls when `github-actions[bot]` pushes to the PR; + # `github.event.workflow_run.conclusion` only runs after a successful analysis workflow. + if: ${{ + github.actor == 'dependabot[bot]' + && github.event.workflow_run.conclusion == 'success' + }} + runs-on: ubuntu-latest + permissions: + # The default GITHUB_TOKEN will be used to enable the "auto-merge" on the PR + # This requires the following two permissions: + contents: write + pull-requests: write + + steps: + + - name: Get pull request metadata + id: pr + env: + # Reference of the payload: https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_run + # + # The structure of `pull_requests` is not documented, so we'll dump it for debugging purposes. + PULL_REQUESTS: ${{ toJSON(github.event.workflow_run.pull_requests) }} + run: | + # Print payload for debugging + jq <<< "$PULL_REQUESTS" Review Comment: This step assumes `github.event.workflow_run.pull_requests[0]` exists. If the `workflow_run` payload has an empty `pull_requests` array (or multiple PRs), this will emit `null` outputs and later steps will fail. Add a guard that checks the array length and errors out with a clear message (or selects the intended PR deterministically). ```suggestion jq <<< "$PULL_REQUESTS" pr_count="$(echo "$PULL_REQUESTS" | jq 'length')" if [ "$pr_count" -ne 1 ]; then echo "::error::Expected workflow_run.pull_requests to contain exactly 1 pull request, found $pr_count." exit 1 fi ``` ########## src/site/antora/modules/ROOT/pages/workflows.adoc: ########## @@ -104,10 +104,64 @@ To verify the reproducibility of a release, you can use: include::example$build.yaml[tag=verify-reproducibility-release,indent=0] ---- -[#merge-dependabot] -== {project-github-url}/blob/main/.github/workflows/merge-dependabot-reusable.yaml[`merge-dependabot-reusable.yaml`] +[#analyze-dependabot] +== {project-github-url}/blob/main/.github/workflows/analyze-dependabot-reusable.yaml[`analyze-dependabot-reusable.yaml`] -Merges Dependabot PRs along with changelog entries. +Analyzes Dependabot pull requests to collect detailed information about updated dependencies. +Stores the results in the `dependabot-metadata` artifact, +which is later consumed by the <<process-dependabot>> workflow to automate changelog generation and PR processing. + +[NOTE] +==== +This workflow must be triggered by an event that includes the `pull_request` payload and does not require any privileges. +It can then be used in a `pull_request` workflow. +==== + +.Snippet from an {examples-base-link}/analyze-dependabot.yaml[example `analyze-dependabot.yaml`] using this workflow +[source,yaml,subs=+attributes] +---- +include::example$analyze-dependabot.yaml[tag=analyze-dependabot,indent=0] +---- + +[#process-dependabot] +== {project-github-url}/blob/main/.github/workflows/process-dependabot-reusable.yaml[`process-dependabot-reusable.yaml`] + +Helps to process Dependabot pull requests by: + +* Generating changelog entries for the updated dependencies. +* Enabling the "auto-merge" option for the pull request. + +The workflow needs the following privileged tokens: + +`GITHUB_TOKEN`:: +The default GitHub token with `contents:write` and `pull_requests:write` permissions, Review Comment: Docs refer to the permission as `pull_requests:write`, but the actual workflow permission key is `pull-requests: write`. Please update the documentation to use the correct permission name so readers configure permissions correctly. ```suggestion The default GitHub token with `contents:write` and `pull-requests: write` permissions, ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
