Skip to content

add check signed commits reusable workflow - #25

Merged
David Gamero (davidgamero) merged 4 commits into
Azure:mainfrom
davidgamero:check-signed-commits
Feb 7, 2026
Merged

add check signed commits reusable workflow#25
David Gamero (davidgamero) merged 4 commits into
Azure:mainfrom
davidgamero:check-signed-commits

Conversation

@davidgamero

@davidgamero David Gamero (davidgamero) commented Feb 6, 2026

Copy link
Copy Markdown
Collaborator

add a workflow for informing users when they don't sign commits instead of finding out at the last second when we can't merge

tested on fork here davidgamero/k8s-deploy#2

leaves a comment like this when unsigned commits are detected.
image

@bosesuneha Suneha Bose (bosesuneha) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@davidgamero
David Gamero (davidgamero) merged commit 0815b2f into Azure:main Feb 7, 2026
5 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a reusable GitHub Actions workflow that checks whether commits in a pull request are signed, and updates documentation to help downstream repos adopt it so unsigned commits are caught early (before merge time).

Changes:

  • Added .github/workflows/check_signed_commits.yaml reusable workflow to detect unsigned PR commits and manage a bot comment.
  • Updated README.md with workflow catalog and usage instructions, including the new signed-commit check.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
README.md Adds workflow inventory and usage examples, including how to wire up the signed-commit check.
.github/workflows/check_signed_commits.yaml New reusable workflow that queries PR commits via gh, comments on unsigned commits, and fails the job when violations exist.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +21 to +33
commits=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/commits --paginate)
commit_count=$(echo "$commits" | jq length)
echo "Found $commit_count commits in PR"
echo "::endgroup::"

echo "::group::Commit verification status"
echo "$commits" | jq -r '.[] | " \(.sha[0:7]) | verified: \(.commit.verification.verified) | \(.commit.message | split("\n")[0])"'
echo "::endgroup::"

# Find unsigned commits
unsigned=$(echo "$commits" | jq -r '.[] | select(.commit.verification.verified == false) | "- `\(.sha[0:7])` \(.commit.message | split("\n")[0])"')
unsigned_count=$(echo "$commits" | jq '[.[] | select(.commit.verification.verified == false)] | length')

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gh api ... --paginate can emit multiple JSON documents (one per page). Using jq length / jq '[...] | length' on that will produce multiple lengths (one per page), which breaks commit_count/unsigned_count for PRs with enough commits to paginate (e.g., >30). Consider using gh api --paginate --jq to stream individual items, or --slurp + a jq expression that merges pages before counting.

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +57
comment_body="⚠️ **Unsigned Commits Detected**

The following commits are not signed:
$unsigned

Please sign your commits before merging. See [GitHub's guide on signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)."

echo "::group::Checking for existing bot comment"
existing_comment=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments --paginate | \
jq -r '.[] | select(.user.login == "github-actions[bot]" and (.body | contains("Unsigned Commits Detected"))) | .id' | head -1)
echo "Existing comment ID: ${existing_comment:-none}"
echo "::endgroup::"

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The multi-line comment_body string includes leading indentation before several lines (e.g., “The following commits…” and the $unsigned list). In GitHub-flavored Markdown, leading spaces can render these lines as a code block and degrade readability; build the string without extra indentation/newline padding so it renders as intended.

Suggested change
comment_body="⚠️ **Unsigned Commits Detected**
The following commits are not signed:
$unsigned
Please sign your commits before merging. See [GitHub's guide on signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)."
echo "::group::Checking for existing bot comment"
existing_comment=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments --paginate | \
jq -r '.[] | select(.user.login == "github-actions[bot]" and (.body | contains("Unsigned Commits Detected"))) | .id' | head -1)
echo "Existing comment ID: ${existing_comment:-none}"
echo "::endgroup::"
comment_body="⚠️ **Unsigned Commits Detected**"$'\n\n'"The following commits are not signed:"$'\n'"$unsigned"$'\n\n'"Please sign your commits before merging. See [GitHub's guide on signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)."
echo "::group::Checking for existing bot comment"
existing_comment=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments --paginate | \
jq -r '.[] | select(.user.login == "github-actions[bot]" and (.body | contains("Unsigned Commits Detected"))) | .id' | head -1)
echo "Existing comment ID: ${existing_comment:-none}"
echo "::endgroup::"
existing_comment=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments --paginate | \
jq -r '.[] | select(.user.login == "github-actions[bot]" and (.body | contains("Unsigned Commits Detected"))) | .id' | head -1)
echo "Existing comment ID: ${existing_comment:-none}"
echo "::endgroup::"

Copilot uses AI. Check for mistakes.
echo "::endgroup::"

# Find unsigned commits
unsigned=$(echo "$commits" | jq -r '.[] | select(.commit.verification.verified == false) | "- `\(.sha[0:7])` \(.commit.message | split("\n")[0])"')

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit subject lines are inserted into a PR comment without escaping/sanitization. A commit message can contain @mentions or other Markdown that triggers unwanted notifications or formatting. Consider neutralizing mentions (e.g., inserting a zero-width space after @) and/or wrapping the subject in inline code to prevent accidental pings.

Suggested change
unsigned=$(echo "$commits" | jq -r '.[] | select(.commit.verification.verified == false) | "- `\(.sha[0:7])` \(.commit.message | split("\n")[0])"')
unsigned=$(echo "$commits" | jq -r '.[] | select(.commit.verification.verified == false) | "- `\(.sha[0:7])` `\(.commit.message | split("\n")[0] | gsub(\"@\"; \"@\u200B\"))`"')

Copilot uses AI. Check for mistakes.
Comment thread README.md
check-signatures:
uses: Azure/action-release-workflows/.github/workflows/check_signed_commits.yaml@main
permissions:
pull-requests: write

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example caller workflow grants only pull-requests: write, but this reusable workflow creates/updates/deletes PR conversation comments via the Issues Comments API. To avoid permission-related failures in repos with restricted default token permissions, document the required permissions explicitly (typically issues: write for commenting and pull-requests: read for listing commits).

Suggested change
pull-requests: write
pull-requests: read
issues: write

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +69 to +72
on:
pull_request:
types: [opened, synchronize, reopened]

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is intended to notify external contributors, note that workflows triggered by pull_request events from forks commonly run with a read-only GITHUB_TOKEN, which prevents creating/updating comments. Consider documenting this limitation and/or recommending a safe pull_request_target-based caller setup (since this workflow only uses the GitHub API, it can be safe when implemented carefully).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants