Skip to content

Commit c5a9787

Browse files
authored
Merge branch 'develop' into wf-log-follow
2 parents 675255e + f7466f7 commit c5a9787

26 files changed

+1409
-1077
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

api/restHandler/NotificationRestHandler.go

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ const (
5151
)
5252

5353
type NotificationRestHandler interface {
54-
SaveNotificationSettings(w http.ResponseWriter, r *http.Request)
5554
SaveNotificationSettingsV2(w http.ResponseWriter, r *http.Request)
5655
UpdateNotificationSettings(w http.ResponseWriter, r *http.Request)
5756
SaveNotificationChannelConfig(w http.ResponseWriter, r *http.Request)
@@ -118,66 +117,6 @@ func NewNotificationRestHandlerImpl(dockerRegistryConfig pipeline.DockerRegistry
118117
}
119118
}
120119

121-
// SaveNotificationSettings will be deprecated in future
122-
func (impl NotificationRestHandlerImpl) SaveNotificationSettings(w http.ResponseWriter, r *http.Request) {
123-
userId, err := impl.userAuthService.GetLoggedInUser(r)
124-
if userId == 0 || err != nil {
125-
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
126-
return
127-
}
128-
var notificationSetting beans.NotificationRequest
129-
err = json.NewDecoder(r.Body).Decode(&notificationSetting)
130-
if err != nil {
131-
impl.logger.Errorw("request err, SaveNotificationSettings", "err", err, "payload", notificationSetting)
132-
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
133-
return
134-
}
135-
impl.logger.Infow("request payload, SaveNotificationSettings", "err", err, "payload", notificationSetting)
136-
err = impl.validator.Struct(notificationSetting)
137-
if err != nil {
138-
impl.logger.Errorw("validation err, SaveNotificationSettings", "err", err, "payload", notificationSetting)
139-
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
140-
return
141-
}
142-
143-
//RBAC
144-
token := r.Header.Get("token")
145-
if isSuperAdmin := impl.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); !isSuperAdmin {
146-
common.WriteJsonResp(w, err, nil, http.StatusForbidden)
147-
return
148-
}
149-
//RBAC
150-
151-
providers := notificationSetting.Providers
152-
153-
if len(providers) != 0 {
154-
for _, provider := range providers {
155-
if provider.Destination == util.SMTP || provider.Destination == util.SES {
156-
if provider.Recipient == "" {
157-
userEmail, err := impl.userAuthService.GetEmailById(int32(provider.ConfigId))
158-
if err != nil {
159-
impl.logger.Errorw("service err, SaveNotificationSettings", "err", err, "payload", notificationSetting)
160-
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
161-
return
162-
}
163-
provider.Recipient = userEmail
164-
}
165-
// get default configID for SES and SMTP
166-
provider.ConfigId = notificationSetting.SesConfigId
167-
}
168-
}
169-
}
170-
171-
res, err := impl.notificationService.CreateOrUpdateNotificationSettings(&notificationSetting, userId)
172-
if err != nil {
173-
impl.logger.Errorw("service err, SaveNotificationSettings", "err", err, "payload", notificationSetting)
174-
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
175-
return
176-
}
177-
w.Header().Set("Content-Type", "application/json")
178-
common.WriteJsonResp(w, nil, res, http.StatusOK)
179-
}
180-
181120
func (impl NotificationRestHandlerImpl) SaveNotificationSettingsV2(w http.ResponseWriter, r *http.Request) {
182121
userId, err := impl.userAuthService.GetLoggedInUser(r)
183122
if userId == 0 || err != nil {

api/router/NotificationRouter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ func NewNotificationRouterImpl(notificationRestHandler restHandler.NotificationR
3232
return &NotificationRouterImpl{notificationRestHandler: notificationRestHandler}
3333
}
3434
func (impl NotificationRouterImpl) InitNotificationRegRouter(configRouter *mux.Router) {
35-
// to maintain backward compatibility, will be deprecated in future
35+
// do not remove it, this path is used in devtcl cli
3636
configRouter.Path("").
37-
HandlerFunc(impl.notificationRestHandler.SaveNotificationSettings).
37+
HandlerFunc(impl.notificationRestHandler.SaveNotificationSettingsV2).
3838
Methods("POST")
3939
// new router to save notification settings
4040
configRouter.Path("/v2").

0 commit comments

Comments
 (0)