Skip to content

Commit 9395ba2

Browse files
authored
Merge pull request #136 from BerryBytes/feat/rajivbb/workflow
feat: implement the Probot App, Notification workflows
2 parents 27db189 + 4b03778 commit 9395ba2

8 files changed

Lines changed: 464 additions & 0 deletions

File tree

.github/mergeable.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
version: 2
2+
mergeable:
3+
- when: pull_request.*, pull_request_review.*
4+
validate:
5+
# Validate PR title
6+
- do: title
7+
must_include:
8+
regex: '^(feat|docs|chore|fix|refactor|test|style|perf)(\(\w+\))?: .{5,}'
9+
message: "Semantic release conventions must be followed. Example: feat(auth): add login page. Title must be at least 5 characters after the prefix."
10+
11+
# Ensure PR description is provided
12+
- do: description
13+
must_include:
14+
regex: "[\\s\\S]{20,}" # At least 20 characters
15+
message: "Please provide a meaningful description of the PR (minimum 20 characters)."
16+
17+
# Ensure PR references an associated issue
18+
- do: description
19+
must_include:
20+
regex: "(Closes|Fixes|Resolves|Addresses)\\s+#[0-9]+(,?\\s*#[0-9]+)*"
21+
message: "PR must reference at least one issue (e.g., Closes #123, Fixes #123, #124)."
22+
23+
# Ensure at least one required label is applied
24+
- do: label
25+
must_include:
26+
regex: "^(bug|enhancement|documentation|feature|refactor|performance|chore|wip|test|ci|security|dependencies)$"
27+
message: "PR must include at least one valid label."
28+
# Ensure PR has at least one assignee
29+
30+
- do: assignee
31+
min:
32+
count: 1
33+
message: "PR must have at least one assignee."
34+
# Ensure PR has at least one reviewer requested
35+
- do: approvals
36+
min:
37+
count: 1
38+
message: "PR must have at least one reviewer requested or approved."
39+
40+
pass:
41+
- do: labels
42+
add:
43+
- "validated"
44+
- do: checks
45+
status: "success"
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
name: Notify (GitHub Events)
2+
3+
permissions:
4+
issues: write
5+
pull-requests: write
6+
contents: read
7+
8+
on:
9+
issues:
10+
types: [opened, edited, reopened, closed, assigned, labeled]
11+
pull_request:
12+
types: [opened, closed, reopened, ready_for_review, review_requested]
13+
pull_request_review:
14+
types: [submitted, edited, dismissed]
15+
issue_comment:
16+
types: [created, edited]
17+
pull_request_review_comment:
18+
types: [created, edited]
19+
20+
jobs:
21+
notify:
22+
runs-on: ubuntu-latest
23+
name: Send Notifications
24+
25+
steps:
26+
- name: Determine Event Type
27+
id: event_info
28+
run: |
29+
EVENT="${{ github.event_name }}"
30+
ACTION="${{ github.event.action }}"
31+
REPO="${{ github.repository }}"
32+
ACTOR="${{ github.actor }}"
33+
REPO_URL="${{ github.server_url }}/${{ github.repository }}"
34+
35+
if [[ "$EVENT" == "issues" ]]; then
36+
TITLE="Issue $ACTION: ${{ github.event.issue.title }}"
37+
URL="${{ github.event.issue.html_url }}"
38+
NUMBER="${{ github.event.issue.number }}"
39+
USER="${{ github.event.issue.user.login }}"
40+
DESCRIPTION="Issue #$NUMBER by $USER"
41+
STATE="${{ github.event.issue.state }}"
42+
EMOJI="🐛"
43+
44+
elif [[ "$EVENT" == "pull_request" ]]; then
45+
NUMBER="${{ github.event.pull_request.number }}"
46+
USER="${{ github.event.pull_request.user.login }}"
47+
URL="${{ github.event.pull_request.html_url }}"
48+
STATE="${{ github.event.pull_request.state }}"
49+
SOURCE="${{ github.event.pull_request.head.ref }}"
50+
TARGET="${{ github.event.pull_request.base.ref }}"
51+
52+
if [[ "$ACTION" == "closed" && "${{ github.event.pull_request.merged }}" == "true" ]]; then
53+
TITLE="PR merged: ${{ github.event.pull_request.title }}"
54+
EMOJI="✅"
55+
STATE="merged"
56+
elif [[ "$ACTION" == "closed" ]]; then
57+
TITLE="PR closed: ${{ github.event.pull_request.title }}"
58+
EMOJI="❌"
59+
else
60+
TITLE="PR $ACTION: ${{ github.event.pull_request.title }}"
61+
EMOJI="🔀"
62+
fi
63+
DESCRIPTION="PR #$NUMBER by $USER: $SOURCE → $TARGET"
64+
65+
elif [[ "$EVENT" == "pull_request_review" ]]; then
66+
TITLE="PR Review: ${{ github.event.pull_request.title }}"
67+
URL="${{ github.event.review.html_url }}"
68+
NUMBER="${{ github.event.pull_request.number }}"
69+
USER="${{ github.event.review.user.login }}"
70+
REVIEW_STATE="${{ github.event.review.state }}"
71+
STATE="${{ github.event.review.state }}"
72+
SOURCE="${{ github.event.pull_request.head.ref }}"
73+
TARGET="${{ github.event.pull_request.base.ref }}"
74+
DESCRIPTION="Review by $USER on PR #$NUMBER"
75+
EMOJI="👀"
76+
77+
elif [[ "$EVENT" == "issue_comment" ]]; then
78+
NUMBER="${{ github.event.issue.number }}"
79+
USER="${{ github.event.comment.user.login }}"
80+
URL="${{ github.event.comment.html_url }}"
81+
STATE="commented"
82+
83+
if [[ "${{ github.event.issue.pull_request }}" != "" ]]; then
84+
TITLE="Comment on PR: ${{ github.event.issue.title }}"
85+
EMOJI="💬"
86+
else
87+
TITLE="Comment on Issue: ${{ github.event.issue.title }}"
88+
EMOJI="💬"
89+
fi
90+
DESCRIPTION="Comment by $USER on #$NUMBER"
91+
92+
elif [[ "$EVENT" == "pull_request_review_comment" ]]; then
93+
TITLE="Comment on PR: ${{ github.event.pull_request.title }}"
94+
URL="${{ github.event.comment.html_url }}"
95+
NUMBER="${{ github.event.pull_request.number }}"
96+
USER="${{ github.event.comment.user.login }}"
97+
STATE="commented"
98+
SOURCE="${{ github.event.pull_request.head.ref }}"
99+
TARGET="${{ github.event.pull_request.base.ref }}"
100+
DESCRIPTION="Review comment by $USER on PR #$NUMBER"
101+
EMOJI="💬"
102+
else
103+
TITLE="GitHub Event: $EVENT"
104+
URL="${{ github.event.repository.html_url }}"
105+
DESCRIPTION="Event triggered in $REPO"
106+
STATE="N/A"
107+
NUMBER="N/A"
108+
USER="$ACTOR"
109+
EMOJI="📢"
110+
fi
111+
112+
echo "title=$TITLE" >> $GITHUB_OUTPUT
113+
echo "url=$URL" >> $GITHUB_OUTPUT
114+
echo "description=$DESCRIPTION" >> $GITHUB_OUTPUT
115+
echo "emoji=$EMOJI" >> $GITHUB_OUTPUT
116+
echo "number=${NUMBER:-N/A}" >> $GITHUB_OUTPUT
117+
echo "user=${USER:-$ACTOR}" >> $GITHUB_OUTPUT
118+
echo "state=${STATE:-N/A}" >> $GITHUB_OUTPUT
119+
echo "source=${SOURCE:-N/A}" >> $GITHUB_OUTPUT
120+
echo "target=${TARGET:-N/A}" >> $GITHUB_OUTPUT
121+
echo "repo_url=$REPO_URL" >> $GITHUB_OUTPUT
122+
123+
- name: Google Chat Notification
124+
if: always()
125+
uses: Co-qn/google-chat-notification@releases/v1
126+
with:
127+
name: ${{ steps.event_info.outputs.title }}
128+
url: ${{ secrets.GOOGLE_CHAT_WEBHOOK }}
129+
status: ${{ job.status }}
130+
131+
- name: Slack Notification
132+
if: always()
133+
uses: slackapi/slack-github-action@v1.24.0
134+
with:
135+
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
136+
payload: |
137+
{
138+
"text": "${{ steps.event_info.outputs.title }}",
139+
"blocks": [
140+
{
141+
"type": "header",
142+
"text": {
143+
"type": "plain_text",
144+
"text": "${{ steps.event_info.outputs.emoji }} ${{ steps.event_info.outputs.title }}"
145+
}
146+
},
147+
{
148+
"type": "section",
149+
"fields": [
150+
{ "type": "mrkdwn", "text": "*Repository:*\n<${{ steps.event_info.outputs.repo_url }}|${{ github.repository }}>" },
151+
{ "type": "mrkdwn", "text": "*Event:*\n${{ github.event_name }}" },
152+
{ "type": "mrkdwn", "text": "*Author:*\n${{ steps.event_info.outputs.user }}" },
153+
{ "type": "mrkdwn", "text": "*Action:*\n${{ github.event.action }}" },
154+
{ "type": "mrkdwn", "text": "*Number:*\n<${{ steps.event_info.outputs.url }}|#${{ steps.event_info.outputs.number }}>" },
155+
{ "type": "mrkdwn", "text": "*State:*\n${{ steps.event_info.outputs.state }}" }
156+
]
157+
},
158+
{
159+
"type": "section",
160+
"text": { "type": "mrkdwn", "text": "${{ steps.event_info.outputs.description }}" }
161+
},
162+
{
163+
"type": "actions",
164+
"elements": [
165+
{ "type": "button", "text": { "type": "plain_text", "text": "View on GitHub" }, "url": "${{ steps.event_info.outputs.url }}", "style": "primary" },
166+
{ "type": "button", "text": { "type": "plain_text", "text": "View Repository" }, "url": "${{ steps.event_info.outputs.repo_url }}" }
167+
]
168+
},
169+
{
170+
"type": "context",
171+
"elements": [
172+
{ "type": "mrkdwn", "text": "Triggered by ${{ github.actor }} • ${{ github.event_name }} event" }
173+
]
174+
}
175+
]
176+
}
177+
env:
178+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

.github/workflows/pre-commit.yaml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
name: Pre-Commit Checks
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- develop
8+
- 'feat/**'
9+
- 'feature/**'
10+
- 'test/**'
11+
- 'chore/**'
12+
- 'fix/**'
13+
- 'hotfix/**'
14+
- 'docs/**'
15+
pull_request:
16+
types: [opened, synchronize, reopened]
17+
18+
jobs:
19+
precommit:
20+
runs-on: ubuntu-latest
21+
22+
steps:
23+
- name: Checkout Repository
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Go
27+
uses: actions/setup-go@v4
28+
with:
29+
go-version: '1.24'
30+
31+
- name: Install goimports
32+
run: |
33+
go install golang.org/x/tools/cmd/goimports@latest
34+
echo "$HOME/go/bin" >> $GITHUB_PATH
35+
36+
- name: Add Go bin to PATH
37+
run: echo "$HOME/go/bin" >> $GITHUB_PATH
38+
39+
- name: Install goimports
40+
run: go install golang.org/x/tools/cmd/goimports@latest
41+
42+
- name: Install golangci-lint v2.7.2
43+
run: |
44+
curl -sSL https://github.com/golangci/golangci-lint/releases/download/v2.7.2/golangci-lint-2.7.2-linux-amd64.tar.gz \
45+
| tar -xz -C $HOME/go/bin --strip-components=1
46+
47+
- name: Set up Python
48+
uses: actions/setup-python@v5
49+
with:
50+
python-version: "3.11"
51+
52+
- name: Install pre-commit
53+
run: |
54+
python -m pip install --upgrade pip
55+
pip install pre-commit
56+
57+
- name: Load Pre-commit Config
58+
run: |
59+
if [ ! -f ".pre-commit-config.yaml" ]; then
60+
echo " No .pre-commit-config.yaml found — downloading BerryBytes global config..."
61+
curl -sSL \
62+
https://raw.githubusercontent.com/BerryBytes/precommit-util/main/global/precommitFile/.pre-commit-config.yaml \
63+
-o .pre-commit-config.yaml
64+
else
65+
echo "✔ Using project's existing .pre-commit-config.yaml"
66+
fi
67+
68+
- name: Inject temporary Stylelint config for CI
69+
run: |
70+
if [ ! -f ".stylelintrc.json" ]; then
71+
echo " Creating temporary .stylelintrc.json for CI..."
72+
cat <<EOF > .stylelintrc.json
73+
{
74+
"extends": "stylelint-config-standard",
75+
"rules": {
76+
"no-duplicate-selectors": true,
77+
"color-hex-length": "short",
78+
"selector-no-qualifying-type": true,
79+
"selector-max-id": 0
80+
}
81+
}
82+
EOF
83+
else
84+
echo "✔ .stylelintrc.json already exists — skipping"
85+
fi
86+
87+
# --------------------------------------------------------------------
88+
# STEP 1: Run pre-commit (capture full logs and exit code safely)
89+
# --------------------------------------------------------------------
90+
- name: Run pre-commit (full logs)
91+
id: runprecommit
92+
run: |
93+
echo "🔍 Running full pre-commit checks..."
94+
95+
set +e # allow failure
96+
pre-commit run --all-files --verbose --show-diff-on-failure --color never \
97+
| tee full_precommit.log
98+
exit_code=${PIPESTATUS[0]}
99+
100+
echo "Pre-commit exit code: $exit_code"
101+
echo "$exit_code" > precommit_exit_code.txt
102+
103+
# --------------------------------------------------------------------
104+
# STEP 2: Summary of FAILED hooks
105+
# --------------------------------------------------------------------
106+
- name: Pre-commit summary of failed hooks
107+
run: |
108+
echo "====================================================="
109+
echo " PRE-COMMIT SUMMARY"
110+
echo "====================================================="
111+
112+
exit_code=$(cat precommit_exit_code.txt)
113+
114+
if [ "$exit_code" = "0" ]; then
115+
echo " All hooks passed!"
116+
exit 0
117+
fi
118+
119+
echo " Hooks failed — showing summary:"
120+
echo ""
121+
122+
echo " FAILED HOOKS:"
123+
grep -E "^\w.*\.{3,}Failed" full_precommit.log || echo " None"
124+
echo "-----------------------------------------------------"
125+
126+
echo " FILES WITH ISSUES:"
127+
grep -E "files were modified by this hook" -A3 full_precommit.log \
128+
| sed 's/^/ - /' || echo " None"
129+
echo "-----------------------------------------------------"
130+
131+
echo " ERROR DETAILS:"
132+
grep -Ei "(error|failed|violation|missing|line too long|could not|warning)" full_precommit.log \
133+
| grep -Ev "^(---|\+\+\+|@@|diff --git|index )" \
134+
| sed 's/^/ • /' || echo " None"
135+
echo "-----------------------------------------------------"
136+
137+
exit $exit_code

0 commit comments

Comments
 (0)