Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace 3rd party workflow actions with Github API to access labels and PR body #1924

Merged
merged 25 commits into from
Jan 3, 2025
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5fdd356
Replacing 3rd party actions with Github API to read labels and body
atmamont Dec 18, 2024
f5cdd5f
Adding missing check for at least one allowed label present
atmamont Dec 18, 2024
2582923
Posting error message as Github comment
atmamont Dec 18, 2024
b594e7e
Use signle quote ticks for label formatting
atmamont Dec 18, 2024
29aee1e
Revert changes as it overcomplicates the post message part of the scr…
atmamont Dec 18, 2024
e65ff34
Update existing github bot comment instead of adding new every time
atmamont Dec 18, 2024
dd38160
Add debug info
atmamont Dec 18, 2024
a4dab62
Proper output to env var for get PR labels step
atmamont Dec 18, 2024
7fbbf56
Simplifying bash code
atmamont Dec 18, 2024
5af8765
Remove comment is success
atmamont Dec 18, 2024
cc1902e
Merge branch 'develop' into make-label-release-notes-workflow-fork-fr…
goergisn Dec 18, 2024
1738e96
Debug info
atmamont Dec 18, 2024
e56844a
Simplify error handling
atmamont Dec 18, 2024
d1e5221
Define a specific type for this workflow comments
atmamont Dec 18, 2024
abf81a2
Add identifier to bot’s comment
atmamont Dec 18, 2024
b7c28b2
Try using double backticks
atmamont Dec 18, 2024
4e1d7f0
More backticks
atmamont Dec 18, 2024
c8e33e2
Now escape all added backticks
atmamont Dec 18, 2024
c9adbc5
Remove curly brackets
atmamont Dec 18, 2024
98f6d8e
KISS
atmamont Dec 18, 2024
6f9ab66
Add permission to manage comments
atmamont Dec 19, 2024
22a2330
Open access to issues
atmamont Dec 19, 2024
932f11a
The last resort: extending access scope to pull_request_target
atmamont Dec 27, 2024
a80b8ba
Merge branch 'develop' into make-label-release-notes-workflow-fork-fr…
atmamont Dec 27, 2024
865054e
Re-enable workflow for base repo
atmamont Dec 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 116 additions & 17 deletions .github/workflows/validate_pr_labels_and_release_notes.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
name: 🏷️ Validate PR labels and release notes

on:
pull_request_target:
types: [opened, synchronize, reopened, labeled, unlabeled, edited]
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled, edited]


permissions:
pull-requests: write
issues: write
goergisn marked this conversation as resolved.
Show resolved Hide resolved
jobs:
get-pr-labels:
runs-on: ubuntu-latest
Expand All @@ -14,6 +18,7 @@ jobs:
fetch-depth: 0

- name: Get the list of allowed pull request labels
id: get-allowed_labels
atmamont marked this conversation as resolved.
Show resolved Hide resolved
run: |
RED='\033[0;31m'
NC='\033[0m'
Expand All @@ -24,29 +29,53 @@ jobs:
exit 1
fi
echo "LABELS=$(cat $FILE_PATH),chore,improvement" >> $GITHUB_OUTPUT
id: get-allowed_labels
env:
PROJECT_ROOT: ${{ github.workspace }}

- name: Validate labels
uses: jesusvasquez333/verify-pr-label-action@v1.4.0
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
valid-labels: ${{ steps.get-allowed_labels.outputs.LABELS }}

- name: Get PR labels
uses: joerick/pr-labels-action@v1.0.9
id: pr-labels
uses: actions/github-script@v7
with:
script: |
const labels = context.payload.pull_request.labels.map(l => l.name).join(',');
console.log('Debug: Found PR labels:', labels);
core.setOutput('labels', labels);
result-encoding: string

- run: |
ALLOWED_LABELS="$ALLOWED_LABELS,chore,improvement"
- name: Validate labels and release notes
id: validate
run: |
ALLOWED_LABELS="$ALLOWED_LABELS"
IFS=',' read -r -a ALLOWED_LABELS_ARRAY <<< "$ALLOWED_LABELS"

SHOULD_FAIL_JOB="false"
IFS=',' read -r -a PR_LABELS_ARRAY <<< "$PR_LABELS"
FORMATTED_LABELS=$(printf "'%s', " "${ALLOWED_LABELS_ARRAY[@]}" | sed 's/, $//')

echo "Debug info:"
echo "Allowed labels: ${ALLOWED_LABELS_ARRAY[@]}"
echo "PR labels: ${PR_LABELS_ARRAY[@]}"

SHOULD_FAIL=false
ERROR_MESSAGE=""

RED='\033[0;31m'
NC='\033[0m'

# Check if PR has any labels
if [ ${#PR_LABELS_ARRAY[@]} -eq 0 ]; then
ERROR_MESSAGE="❌ This pull request does not contain a valid label. Please add one of the following labels: [${FORMATTED_LABELS}]"
SHOULD_FAIL=true
fi

# Validate labels exist in allowed list
for LABEL in "${PR_LABELS_ARRAY[@]}"; do
if [[ ! " ${ALLOWED_LABELS_ARRAY[@]} " =~ " ${LABEL} " ]]; then
ERROR_MESSAGE="❌ This pull request contains invalid label: '${LABEL}'. Please use one of the following labels: [${FORMATTED_LABELS}]"
SHOULD_FAIL=true
break
fi
done

# Validate release notes
for LABEL in "${ALLOWED_LABELS_ARRAY[@]}"; do
LABEL=$(echo "$LABEL" | sed 's/^ *//g' | sed 's/ *$//g')
if [[ "$LABEL" == "chore" || "$LABEL" == "improvement" ]]; then
Expand All @@ -56,15 +85,85 @@ jobs:
cmd="awk '/<$LABEL>.*<\/$LABEL>/'"
FEATURE_RELEASE_NOTE="$(echo $PR_BODY | eval $cmd)"
if [[ -z "$FEATURE_RELEASE_NOTE" ]]; then
echo -e "${RED}Pull requests labeled with '$LABEL' must have the release note in the pull request body in the following format '<$LABEL> {THE RELEASE NOTE} </$LABEL>'${NC}"
SHOULD_FAIL_JOB="true"
ERROR_MESSAGE="❌ Pull requests labeled with '${LABEL}' must have the release note wrapped in the same xml tag."
atmamont marked this conversation as resolved.
Show resolved Hide resolved
SHOULD_FAIL=true
break
fi
fi
done
if [[ "$SHOULD_FAIL_JOB" == "true" ]]; then

if [ "$SHOULD_FAIL" = true ]; then
echo "$ERROR_MESSAGE"
echo "error_message=${ERROR_MESSAGE}" >> $GITHUB_OUTPUT
exit 1
fi

env:
PR_BODY: ${{github.event.pull_request.body}}
PR_LABELS: ${{steps.pr-labels.outputs.labels}}
ALLOWED_LABELS: ${{ steps.get-allowed_labels.outputs.LABELS }}
atmamont marked this conversation as resolved.
Show resolved Hide resolved

- name: Post or update error comment
if: failure() && steps.validate.outputs.error_message != ''
uses: actions/github-script@v7
with:
script: |
const commentIdentifier = '<!-- pr-labels-check -->';
const errorMessage = `${commentIdentifier}\n${`${{ steps.validate.outputs.error_message }}`}`;

// First find if we already have a comment from the bot
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});

const botComment = comments.find(comment =>
comment.user.login === 'github-actions[bot]' &&
comment.body.includes(commentIdentifier)
);

atmamont marked this conversation as resolved.
Show resolved Hide resolved

if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: errorMessage
});
} else {
// Create new comment if none exists
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: errorMessage
});
}

- name: Remove error comment if exists
if: success()
uses: actions/github-script@v7
with:
script: |
const commentIdentifier = '<!-- pr-labels-check -->';

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});

const botComment = comments.find(comment =>
comment.user.login === 'github-actions[bot]' &&
comment.body.includes(commentIdentifier)
);

if (botComment) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id
});
}
Loading