Adding Check and Apply Header workflow files - #319
danielsoden0404 wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds two GitHub Actions workflows to (1) detect missing copyright/license headers on pull requests and (2) apply the expected header template to matching files via a manual dispatch workflow. This fits into the repo’s automation by standardizing source-file headers based on the NOTICE file content.
Changes:
- Introduces a PR-facing “check” workflow that builds a header template from
NOTICE, runsaddlicense -check, and posts/updates a PR comment with results. - Introduces a manual “apply” workflow that generates the same template, applies headers with
addlicense, and commits/pushes the changes back to the selected branch.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| .github/workflows/check-headers.yml | Adds PR check workflow that generates a header template from NOTICE, runs addlicense -check, and comments on the PR with missing-header results and the header preview. |
| .github/workflows/apply-headers.yml | Adds manual workflow that applies the same header template via addlicense, then commits and pushes changes to the branch. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (3)
.github/workflows/check-headers.yml:165
- The comment lookup can return multiple matching IDs; assigning them to COMMENT_ID and using it in a single DELETE call can fail (newline-separated IDs) and can also leave older matching comments behind. Consider deleting all matching bot comments, or at least selecting one deterministically.
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${GITHUB_PULL_REQUEST_NUMBER}/comments" -q '.[] | select(.user.login=="github-actions[bot]" and (.body | contains("Automated Copyright License Check"))) | .id')
if [ -z "$COMMENT_ID" ]; then
echo "Creating new copyright check warning comment"
else
.github/workflows/apply-headers.yml:101
- The heredoc content lines are indented, which will be written into /tmp/copyright.tmpl as leading whitespace. That will produce headers with extra spaces at the start of each line when addlicense applies them.
chmod 0600 /tmp/copyright.tmpl
.github/workflows/check-headers.yml:103
- The heredoc content lines are indented, which will be written into /tmp/copyright.tmpl as leading whitespace. That will produce headers with extra spaces at the start of each line (e.g., "// Copyright ..."), which can cause header mismatches and looks incorrect when applied to source files.
chmod 0600 /tmp/copyright.tmpl
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (2)
.github/workflows/check-headers.yml:162
gh api ... -q '.[] | select(...) | .id'can return multiple matching comment IDs (one per line). In that caseCOMMENT_IDbecomes a multiline string and the subsequent DELETE request will fail. Consider selecting a single comment (e.g., the most recent match) or iterating over all matches.
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${GITHUB_PULL_REQUEST_NUMBER}/comments" -q '.[] | select(.user.login=="github-actions[bot]" and (.body | contains("Automated Copyright License Check"))) | .id')
.github/workflows/check-headers.yml:33
- The NOTICE parsing + template creation logic is duplicated across
check-headers.ymlandapply-headers.yml(e.g., compare this step with.github/workflows/apply-headers.yml:27-101). This increases the risk that the check/apply workflows drift and start generating different expected headers. Consider extracting the shared logic into a composite action (or a reusable workflow) and calling it from both workflows.
- name: Extract organisation from NOTICE file from root
id: extract_organisation
run: |
if [ ! -f NOTICE ]; then
echo "::error file=NOTICE::NOTICE file is required at the repository root"
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (3)
.github/workflows/check-headers.yml:168
COMMENT_IDcan contain multiple IDs if there are multiple previous bot comments matching the filter; passing a multi-line value into the DELETE endpoint will fail. Collect all matching IDs and delete them in a loop (or select a single ID explicitly).
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${GITHUB_PULL_REQUEST_NUMBER}/comments" -q '.[] | select(.user.login=="github-actions[bot]" and (.body | contains("Automated Copyright License Check"))) | .id')
if [ -z "$COMMENT_ID" ]; then
echo "Creating new copyright check warning comment"
else
echo "Replacing old copyright check warning comment"
gh api -X DELETE "repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}"
fi
.github/workflows/check-headers.yml:9
- The PR-comment step uses the Issues Comments REST API endpoints, but the workflow token permissions do not grant
issues: write. This is likely to fail with a 403 when creating/deleting the comment; addissues: write(you can keeppull-requests: writeif needed elsewhere).
permissions:
contents: read
pull-requests: write
.github/workflows/check-headers.yml:44
- The NOTICE parsing + template creation logic is duplicated across
check-headers.ymlandapply-headers.yml. This makes future changes to the header format/error handling easy to accidentally apply to only one workflow; consider extracting these steps into a reusable workflow or composite action and calling it from both workflows.
- name: Extract organisation from NOTICE file from root
id: extract_organisation
run: |
if [ ! -f NOTICE ]; then
echo "::error file=NOTICE::NOTICE file is required at the repository root"
exit 1
fi
copyright_line=$(grep -im1 'copyright' NOTICE || true)
if [ -z "$copyright_line" ]; then
echo "::error file=NOTICE::NOTICE must contain a copyright line"
exit 1
fi
organisation=$(printf '%s\n' "$copyright_line" | sed -E 's/.*[Cc]opyright( \(c\))?[[:space:]]*//; s/^([0-9]{4}([[:space:]]*[-,][[:space:]]*[0-9]{4})*[[:space:]]*)+//; s/[[:space:]]+$//; s/\.$//')
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (4)
.github/workflows/check-headers.yml:161
COMMENT_IDis derived from a jq filter that can return multiple comment IDs (and the issues comments API is paginated by default). If more than one matching bot comment exists, or the bot comment is older than the first page of results, this variable can contain multiple IDs or be empty, causing the delete call to fail and duplicate comments to accumulate. Paginate and select a single ID (e.g., the most recent) before deleting.
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${GITHUB_PULL_REQUEST_NUMBER}/comments" -q '.[] | select(.user.login=="github-actions[bot]" and (.body | contains("Automated Copyright License Check"))) | .id')
.github/workflows/check-headers.yml:150
- The success message is grammatically off (singular “header” while referring to multiple files).
echo 'No files missing copyright header.'
.github/workflows/check-headers.yml:127
- The
findcommand scans ignored directories (node_modules/build/dist/.github) and relies onaddlicense -ignoreto skip them later. This can significantly increase runtime on large repos; it's more efficient to exclude these paths infindas well.
if ! find . -not -path './.git/*' -type f \( "${FIND_ARGS[@]}" \) -print0 | \
.github/workflows/apply-headers.yml:129
- As in the check workflow,
findcurrently scans ignored directories and relies onaddlicense -ignoreto skip them. Excluding these paths infindcan reduce runtime and resource usage.
find . -not -path './.git/*' -type f \( "${FIND_ARGS[@]}" \) -print0 | \
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (16)
.github/workflows/apply-headers.yml:126
addlicensev1.2.0 accepts-ignoreas one comma-separated option. Passing the flag four times causes the later value to replace the earlier ones, so only**/.github/**is ignored; files undernode_modules,build, anddistcan then be checked or modified. PassIGNORE_PATTERNas a single-ignoreargument (or use the tool's supported pattern syntax).
IFS=',' read -r -a IGNORE_ARRAY <<< "$IGNORE_PATTERN"
IGNORE_FLAGS=()
for pattern in "${IGNORE_ARRAY[@]}"; do
IGNORE_FLAGS+=("-ignore" "$pattern")
done
.github/workflows/apply-headers.yml:106
- The repository contains HTML source files with these headers (for example,
framework/fileStore/lightning-apps/htmlplayer.html), but*.htmlis absent from the include list. A new or modified HTML file without a header will therefore be skipped by the apply workflow, so it will not add headers to all supported source files.
INCLUDE_PATTERN: "**/*.c,**/*.cc,**/*.cpp,**/*.cxx,**/*.h,**/*.hh,**/*.hpp,**/*.hxx,**/*.go,**/*.sh,**/*.bash,**/*.py,**/*.java,**/*.js,**/*.ts"
.github/workflows/apply-headers.yml:142
workflow_dispatchcan be run against a tag as well as a branch, but this refspec always treatsGITHUB_REF_NAMEas a branch destination. Running the workflow on a tag can create or update an unintended branch, or fail, instead of pushing the selected ref. Restrict the workflow to branch refs before committing and pushing.
git push origin "HEAD:${GITHUB_REF_NAME}"
.github/workflows/apply-headers.yml:142
- This push uses the checkout's
GITHUB_TOKEN, so GitHub suppresses downstream workflow runs caused by the push. Thepull_requestcheck therefore will not rerun after headers are applied, leaving the prior missing-header comment stale even though the branch is now fixed. Trigger an explicit check with pull-request context or update/replace the comment from the apply workflow.
git push origin "HEAD:${GITHUB_REF_NAME}"
.github/workflows/apply-headers.yml:85
- The template contains a literal space before
{{.Year}}inside the conditional, in addition to the space before{{ if ... }}. Go templates preserve both spaces, so addlicense will writeCopyright 2026 RDK Managementinstead of the repository's single-space header. Move the conditional's space after the year.
Copyright {{ if .Year }} {{.Year}}{{ end }} ${ORGANISATION}
.github/workflows/apply-headers.yml:64
- The Comcast template has the same whitespace issue: the space inside
{{ if .Year }}is preserved in addition to the preceding literal space, so addlicense writes two spaces betweenCopyrightand the year. Move the conditional's space after the year.
Copyright {{ if .Year }} {{.Year}}{{ end }} ${ORGANISATION}
.github/workflows/check-headers.yml:124
addlicensev1.2.0 accepts-ignoreas one comma-separated option. Passing the flag four times causes the later value to replace the earlier ones, so only**/.github/**is ignored; files undernode_modules,build, anddistcan then be checked or modified. PassIGNORE_PATTERNas a single-ignoreargument (or use the tool's supported pattern syntax).
IFS=',' read -r -a IGNORE_ARRAY <<< "$IGNORE_PATTERN"
IGNORE_FLAGS=()
for pattern in "${IGNORE_ARRAY[@]}"; do
IGNORE_FLAGS+=("-ignore" "$pattern")
done
.github/workflows/check-headers.yml:85
- The generic template says
this component's LICENSE file, but the repository's existing headers consistently usethis component's Licenses.txt(for example,framework/fileStore/lightning-apps/htmlplayer.html:2andutilities/TDK_Automation_Scripts/python-lib/resetAgent.py:3). Because this is the template passed toaddlicense -check, existing files will be reported as missing and the apply workflow can prepend a second header instead of recognizing them. Match the existing header wording, or migrate the existing headers before enabling this check.
If not stated otherwise in this file or this component's LICENSE file the
following copyright and licenses apply:
.github/workflows/check-headers.yml:109
- The repository contains HTML source files with these headers (for example,
framework/fileStore/lightning-apps/htmlplayer.html), but*.htmlis absent from the include list. A new or modified HTML file without a header will therefore be skipped by the check workflow, so the advertised coverage is incomplete.
INCLUDE_PATTERN: "**/*.c,**/*.cc,**/*.cpp,**/*.cxx,**/*.h,**/*.hh,**/*.hpp,**/*.hxx,**/*.go,**/*.sh,**/*.bash,**/*.py,**/*.java,**/*.js,**/*.ts"
.github/workflows/check-headers.yml:127
- Any nonzero status from this pipeline is interpreted as "files missing headers." That also covers
find,xargs, andaddlicenseexecution errors such as unreadable input or a malformed template; the script then writes a misleading missing-header comment and exits successfully. Capture operational failures separately and only build the missing-file report for the expected addlicense check result.
if ! find . -not -path './.git/*' -type f \( "${FIND_ARGS[@]}" \) -print0 | \
xargs -0 -r addlicense -f /tmp/copyright.tmpl "${IGNORE_FLAGS[@]}" -check > /tmp/addlicense_output.txt 2>&1; then
.github/workflows/check-headers.yml:161
- This lookup reads only the first API page and emits every matching comment ID. Once a pull request has more than the default page size, the old bot comment is not found and another is created; if duplicate comments exist from concurrent runs, the newline-separated IDs make the single DELETE URL invalid. Paginate the lookup and delete or replace matching IDs individually (or select one deterministically).
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${GITHUB_PULL_REQUEST_NUMBER}/comments" -q '.[] | select(.user.login=="github-actions[bot]" and (.body | contains("Automated Copyright License Check"))) | .id')
.github/workflows/check-headers.yml:143
- The preview substitutes the year when the check runs, while the apply workflow leaves
.Yearfor addlicense to resolve when the manual workflow runs. A dispatch after a calendar-year rollover therefore commits a different header from the one shown in the pull request comment, so the preview is not exact. Persist or pass a fixed year to both workflows, or regenerate the preview from the value used by apply.
sed "s/{{ if \.Year }} {{\.Year}}{{ end }}/${current_year}/" /tmp/copyright.tmpl
.github/workflows/check-headers.yml:66
- The Comcast template has the same whitespace issue: the space inside
{{ if .Year }}is preserved in addition to the preceding literal space, producing two spaces betweenCopyrightand the year. This also makes the header written by addlicense differ from the one shown by the check workflow. Move the conditional's space after the year and update the check workflow's replacement expression too.
Copyright {{ if .Year }} {{.Year}}{{ end }} ${ORGANISATION}
.github/workflows/check-headers.yml:87
- The template contains a literal space before
{{.Year}}inside the conditional, in addition to the space before{{ if ... }}. Go templates preserve both spaces, so addlicense will renderCopyright 2026 RDK Management, while thesedoutput in this workflow and the repository's existing headers use a single space. Move the conditional's space after the year and update the replacement expression below so the applied and displayed headers remain identical.
Copyright {{ if .Year }} {{.Year}}{{ end }} ${ORGANISATION}
.github/workflows/apply-headers.yml:83
- The generic template says
this component's LICENSE file, but the repository's existing headers consistently usethis component's Licenses.txt(for example,framework/fileStore/lightning-apps/htmlplayer.html:2andutilities/TDK_Automation_Scripts/python-lib/resetAgent.py:3). Because this is the template passed toaddlicense, existing files will not match the header this workflow is intended to apply, so the apply run can prepend a second header. Match the existing header wording, or migrate the existing headers before enabling this workflow.
This issue also appears on line 122 of the same file.
If not stated otherwise in this file or this component's LICENSE file the
following copyright and licenses apply:
.github/workflows/check-headers.yml:9
- For a fork-originated
pull_request, GitHub normally downgradesGITHUB_TOKENpermissions to read-only, so the finalgh pr commentcall cannot create or delete comments even thoughpull-requests: writeis declared here. The check therefore fails for ordinary fork PRs; use a trusted comment job that does not execute pull-request code (or otherwise handle fork events without requiring write access).
This issue also appears in the following locations of the same file:
- line 84
- line 120
permissions:
contents: read
pull-requests: write
Copyright Header Workflows
Check workflow
The check workflow is intended to run on pull requests.
Functionality:
NOTICEfileNOTICEIf all matching files already contain the expected header, the workflow posts a success comment instead.
Apply workflow
The apply workflow will be ran manually with
workflow_dispatchafter a pull requestFunctionality:
github-actions[bot]