Skip to content

Commit 782f024

Browse files
committed
fix: centralised PR validator
1 parent 65e1424 commit 782f024

File tree

1 file changed

+13
-253
lines changed

1 file changed

+13
-253
lines changed

.github/workflows/pr-issue-validator.yaml

Lines changed: 13 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -11,275 +11,35 @@ on:
1111
- 'main'
1212
- 'release-**'
1313
- 'develop'
14-
- 'hotfix-v0**'
14+
- 'hotfix-**'
1515
# paths-ignore:
1616
# - 'docs/**'
1717
# - '.github/'
1818
# - 'CHANGELOG/'
1919
# - 'charts/'
2020
# - 'manifests/'
2121
# - 'sample-docker-templates/'
22-
2322
jobs:
2423
validate-PR-issue:
2524
runs-on: ubuntu-latest
26-
permissions:
27-
issues: write
28-
contents: read
29-
pull-requests: write
30-
repository-projects: read
25+
3126
steps:
3227
- name: Checkout repository
3328
uses: actions/checkout@v2
34-
with:
35-
ref: ${{ github.event.pull_request.head.sha }}
36-
fetch-depth: 0
3729

38-
- name: Validate Issue Reference
30+
- name: Set up jq (for parsing JSON)
31+
run: sudo apt-get install -y jq
32+
33+
- name: PR Validation Script
3934
env:
40-
GH_TOKEN: ${{ github.token }}
4135
PR_BODY: ${{ github.event.pull_request.body }}
4236
PRNUM: ${{ github.event.pull_request.number }}
4337
TITLE: ${{ github.event.pull_request.title }}
38+
GH_TOKEN: ${{ github.token }}
39+
GH_PR_VALIDATOR_TOKEN: ${{ secrets.GH_PR_VALIDATOR_TOKEN }}
40+
BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }}
41+
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
4442
run: |
45-
46-
echo "base or target repo : ${{ github.event.pull_request.base.repo.full_name }}"
47-
echo "head or source repo : ${{ github.event.pull_request.head.repo.full_name }}"
48-
49-
if [[ ${{ github.event.pull_request.head.repo.full_name }} == ${{ github.event.pull_request.base.repo.full_name }} ]]; then
50-
export forked=false
51-
else
52-
export forked=true
53-
fi
54-
55-
set -x
56-
# Skip validation for documentation or chore PRs
57-
if [[ "$TITLE" =~ ^(doc:|docs:|chore:|misc:|Release:|release:|Sync:|sync:) ]]; then
58-
echo "Skipping validation for docs/chore PR."
59-
echo "PR NUMBER-: $PRNUM "
60-
gh pr edit $PRNUM --remove-label "PR:Issue-verification-failed"
61-
gh pr edit $PRNUM --add-label "PR:Ready-to-Review"
62-
exit 0
63-
fi
64-
65-
# Define all issue matching patterns
66-
patterns=(
67-
"((Fixes|Resolves) #[0-9]+)"
68-
"((Fixes|Resolves) https://github.com/devtron-labs/devtron/issues/[0-9]+)"
69-
"((Fixes|Resolves) devtron-labs/devtron#[0-9]+)"
70-
"(Fixes|Resolves):?\\s+\\[#([0-9]+)\\]"
71-
"((Fixes|Resolves):? #devtron-labs/devops-sprint/issues/[0-9]+)"
72-
"((Fixes|Resolves):? #devtron-labs/sprint-tasks/issues/[0-9]+)"
73-
"((Fixes|Resolves) https://github.com/devtron-labs/devops-sprint/issues/[0-9]+)"
74-
"((Fixes|Resolves) https://github.com/devtron-labs/sprint-tasks/issues/[0-9]+)"
75-
"((Fixes|Resolves):? #devtron-labs/sprint-tasks#[0-9]+)"
76-
)
77-
78-
# Extract issue number and repo from PR body
79-
extract_issue_number() {
80-
local pattern="$1" # Get the pattern as the first argument to the function
81-
82-
# Check if PR_BODY matches the provided pattern using Bash's =~ regex operator
83-
if [[ "$PR_BODY" =~ $pattern ]]; then
84-
echo "matched for this pattern $pattern"
85-
86-
issue_num=$(echo "$PR_BODY" | grep -oE "$pattern" | grep -oE "[0-9]+")
87-
88-
# Extract the repository name (e.g., devtron-labs/devtron) from PR_BODY using grep
89-
repo=$(echo "$PR_BODY" | grep -oE "devtron-labs/[a-zA-Z0-9_-]+")
90-
echo "Extracted issue number: $issue_num from repo: $repo"
91-
92-
return 0 # Return success
93-
else
94-
echo "No match for the pattern $pattern"
95-
fi
96-
return 1 # Return failure if no match
97-
}
98-
99-
issue_num=""
100-
repo="devtron-labs/devtron" # Default repo
101-
for pattern in "${patterns[@]}"; do
102-
echo "Now checking for $pattern"
103-
extract_issue_number "$pattern" && break
104-
done
105-
106-
if [[ -z "$issue_num" ]]; then
107-
echo "No valid issue number found."
108-
gh pr edit $PRNUM --add-label "PR:Issue-verification-failed"
109-
gh pr edit $PRNUM --remove-label "PR:Ready-to-Review"
110-
exit 1
111-
fi
112-
113-
# Form the issue API URL dynamically
114-
issue_api_url="https://api.github.com/repos/$repo/issues/$issue_num"
115-
echo "API URL: $issue_api_url"
116-
117-
if [[ $repo == "devtron-labs/devtron" || $repo == "devtron-labs/devtron-services" || $repo == "devtron-labs/dashboard" ]]; then
118-
echo "No extra arguments needed: public repository detected."
119-
response_code=$(curl -s -o /dev/null -w "%{http_code}" \
120-
"$issue_api_url")
121-
122-
else
123-
echo "Adding extra arguments for authentication: private repository detected."
124-
response_code=$(curl -s -o /dev/null -w "%{http_code}" \
125-
--header "authorization: Bearer ${{ secrets.GH_PR_VALIDATOR_TOKEN }}" \
126-
"$issue_api_url")
127-
fi
128-
129-
echo "Response Code: $response_code"
130-
if [[ "$response_code" -eq 200 ]]; then
131-
echo "Issue #$issue_num is valid and exists in $repo."
132-
133-
# Fetch the current state of the issue (open/closed) from the private repository.
134-
if [[ $repo == "devtron-labs/devtron" || $repo == "devtron-labs/devtron-services" || $repo == "devtron-labs/dashboard" ]]; then
135-
echo "No extra arguments needed: public repository detected."
136-
issue_status=$(curl -s \
137-
"$issue_api_url"| jq '.state'|tr -d \")
138-
else
139-
echo "Adding extra arguments for authentication: private repository detected."
140-
issue_status=$(curl -s \
141-
--header "authorization: Bearer ${{ secrets.GH_PR_VALIDATOR_TOKEN }}" \
142-
"$issue_api_url"| jq '.state'|tr -d \")
143-
fi
144-
echo "Issue Number : $issue_num Status: $issue_status"
145-
# Check if the issue is still open.
146-
# if [[ "$issue_status" == open ]]; then
147-
# echo "Issue #$issue_num is opened."
148-
if [[ $forked == true ]]; then
149-
echo "PR:Ready-to-Review, exiting gracefully"
150-
exit 0
151-
fi
152-
# Remove the 'Issue-verification-failed' label (if present) and add 'Ready-to-Review'.
153-
gh pr edit $PRNUM --remove-label "PR:Issue-verification-failed"
154-
gh pr edit $PRNUM --add-label "PR:Ready-to-Review"
155-
echo "PR:Ready-to-Review, exiting gracefully"
156-
exit 0
157-
# else
158-
# echo "Issue #$issue_num is closed. Please link an open issue to proceed."
159-
# if [[ $forked == true ]]; then
160-
# echo "PR:Ready-to-Review, exiting gracefully"
161-
# exit 0
162-
# fi
163-
# Add a comment to the PR indicating the issue is not linked correctly.
164-
# gh pr comment $PRNUM --body "PR is linked to a closed issue. Please link an open issue to proceed."
165-
166-
# Add the 'Issue-verification-failed' label and remove 'Ready-to-Review'.
167-
# gh pr edit $PRNUM --add-label "PR:Issue-verification-failed"
168-
# gh pr edit $PRNUM --remove-label "PR:Ready-to-Review"
169-
# exit 1
170-
#fi
171-
else
172-
echo "Issue not found. Invalid URL or issue number."
173-
# Add a comment to the PR indicating the issue is not linked correctly.
174-
gh pr comment $PRNUM --body "PR is not linked to a valid issue. Please update the issue link."
175-
176-
# Apply 'Issue-verification-failed' label and remove 'Ready-to-Review' label.
177-
gh pr edit $PRNUM --add-label "PR:Issue-verification-failed"
178-
gh pr edit $PRNUM --remove-label "PR:Ready-to-Review"
179-
exit 1
180-
fi
181-
- name: Check SQL file format and duplicates
182-
shell: bash
183-
env:
184-
pr_no: ${{ github.event.pull_request.number }}
185-
GH_TOKEN: ${{ github.token }}
186-
run: |
187-
# Fetch the latest changes from the main branch
188-
git fetch origin main
189-
190-
# Get the list of changed files
191-
git diff origin/main...HEAD --name-only > diff
192-
193-
# Specify the directory containing migration files
194-
MIGRATION_DIR="scripts/sql"
195-
ls
196-
pwd
197-
198-
# Print changed files
199-
echo "Changed files:"
200-
cat diff
201-
202-
changed_files=""
203-
while IFS= read -r file; do
204-
if [[ $file == $MIGRATION_DIR/* && $file == *.up.sql ]]; then
205-
changed_files+="$file\n"
206-
fi
207-
done < diff
208-
209-
# Print the filtered .up.sql files
210-
echo "Filtered .up.sql files:"
211-
echo -e "$changed_files"
212-
213-
# Check if there are any .up.sql migration files in the changed files list
214-
if [ -z "$changed_files" ]; then
215-
echo "No .up.sql migration files found in the changes."
216-
else
217-
# Extract unique migration numbers from the directory (considering only .up.sql files)
218-
existing_migrations=$(ls $MIGRATION_DIR | grep -E "\.up\.sql$" | grep -oE "[0-9]{3}[0-9]{3}[0-9]{2}" | sort | uniq)
219-
220-
# Exclude migration numbers from changed files in existing_migrations
221-
while read -r file; do
222-
migration_number=$(basename "$file" | grep -oE "[0-9]{3}[0-9]{3}[0-9]{2}")
223-
existing_migrations=$(echo "$existing_migrations" | grep -v "$migration_number")
224-
done <<< "$changed_files"
225-
226-
# Validate each changed .up.sql migration file
227-
is_valid=true
228-
processed_migrations=()
229-
while read -r file; do
230-
# Extract migration number from the filename
231-
migration_number=$(basename "$file" | grep -oE "[0-9]{3}[0-9]{3}[0-9]{2}")
232-
233-
# Check if the filename has the full XXXPPPNN format
234-
if [[ ! $(basename "$file") =~ ^[0-9]{3}[0-9]{3}[0-9]{2}_ ]]; then
235-
echo "Error: Migration file $file does not have the complete XXXPPPNN format."
236-
is_valid=false
237-
continue
238-
fi
239-
240-
if [ -z "$migration_number" ]; then
241-
echo "Warning: Could not extract migration number from $file."
242-
continue
243-
fi
244-
245-
# Check if this migration number has already been processed
246-
if [[ " ${processed_migrations[@]} " =~ " $migration_number " ]]; then
247-
continue
248-
fi
249-
processed_migrations+=("$migration_number")
250-
251-
# Check if the migration number is unique
252-
if echo "$existing_migrations" | grep -q "$migration_number"; then
253-
echo "Error: Migration number $migration_number already exists."
254-
is_valid=false
255-
fi
256-
257-
# Check if the migration number is greater than previous ones
258-
last_migration=$(echo "$existing_migrations" | tail -n 1)
259-
if [ "$migration_number" -le "$last_migration" ]; then
260-
echo "Error: Migration number $migration_number is not greater than the latest ($last_migration)."
261-
is_valid=false
262-
fi
263-
264-
# Check for sequential hotfix requirement (if NN > 01, check for NN-1)
265-
hotfix_number=$(echo "$migration_number" | grep -oE "[0-9]{2}$")
266-
if [ "$hotfix_number" -gt "01" ]; then
267-
previous_hotfix=$(printf "%02d" $((10#$hotfix_number - 1)))
268-
expected_previous_number="${migration_number:0:6}$previous_hotfix"
269-
if ! echo "$existing_migrations" | grep -q "$expected_previous_number"; then
270-
echo "Error: Previous hotfix migration $expected_previous_number not found for $migration_number."
271-
is_valid=false
272-
fi
273-
fi
274-
275-
done <<< "$changed_files"
276-
277-
if [ "$is_valid" = false ]; then
278-
echo "Validation failed. Please fix the errors before merging."
279-
gh pr comment $pr_no --body "The Migration files providede inside of the PR does not pass the criteria!!"
280-
exit 1
281-
fi
282-
283-
echo "All .up.sql migration file validations passed."
284-
gh pr comment $pr_no --body "The migration files have successfully passed the criteria!!"
285-
fi
43+
wget https://raw.githubusercontent.com/devtron-labs/utilities/feat/central-pr-validator/.github/workflows/validateIssue.sh
44+
chmod +x validateIssue.sh
45+
./validateIssue.sh

0 commit comments

Comments
 (0)