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-   
2322jobs :
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