Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 29 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## CHANGELOG
REPLACE_ME_WITH_CHANGELOG

## SUMMARY
REPLACE_ME_WITH_SUMMARY_OF_THE_CHANGES
Comment on lines +1 to +5
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The template starts directly with a level-2 heading (## CHANGELOG) instead of a single top-level heading, which can reduce readability and consistency with common PR template structures.

Why: Having a clear top-level title (e.g., "Pull Request Template" or "PR Details") improves readability, especially when rendered in GitHub’s UI, and makes it easier for contributors to understand the structure at a glance.

How to Fix: Add a level-1 heading at the top of the file and keep the existing sections as subsections.

Suggested change
## CHANGELOG
REPLACE_ME_WITH_CHANGELOG
## SUMMARY
REPLACE_ME_WITH_SUMMARY_OF_THE_CHANGES
# Pull Request Details
## CHANGELOG
REPLACE_ME_WITH_CHANGELOG
## SUMMARY
REPLACE_ME_WITH_SUMMARY_OF_THE_CHANGES


## FUNCTIONAL AUTOMATION CHANGES PR
- [ ] Yes
- If Yes, PR :
- [ ] No
- If No, Reason:
Comment on lines +7 to +11
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The "FUNCTIONAL AUTOMATION CHANGES PR" section uses free-text fields ("If Yes, PR :" / "If No, Reason:") which may lead to inconsistent input and missing links or reasons.

Why: Inconsistent formatting makes it harder to parse PRs (both for humans and any future automation) and increases the chance that authors forget to provide the required PR link or reason.

How to Fix: Replace the free-text prompts with clearly labeled placeholders on the same line, making it obvious what needs to be filled and encouraging consistent formatting.

Suggested change
## FUNCTIONAL AUTOMATION CHANGES PR
- [ ] Yes
- If Yes, PR :
- [ ] No
- If No, Reason:
## FUNCTIONAL AUTOMATION CHANGES PR
- [ ] Yes — Related automation PR: REPLACE_ME_WITH_AUTOMATION_PR_LINK
- [ ] No — Reason: REPLACE_ME_WITH_REASON_FOR_NO_AUTOMATION_CHANGES


## AUTOMATION TEST REPORT URL
REPLACE_ME_WITH_TEST_REPORT_URL
Comment on lines +13 to +14
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The "AUTOMATION TEST REPORT URL" section uses a generic placeholder without clarifying that "N/A" is acceptable when not applicable.

Why: Without explicit guidance, contributors may leave this blank or provide inconsistent values, making it harder to quickly see whether tests were run or are not applicable.

How to Fix: Update the placeholder to explicitly allow "N/A" and encourage a consistent format.

Suggested change
## AUTOMATION TEST REPORT URL
REPLACE_ME_WITH_TEST_REPORT_URL
## AUTOMATION TEST REPORT URL
REPLACE_ME_WITH_TEST_REPORT_URL_OR_NA


## AREAS OF IMPACT
REPLACE_ME_WITH_AREAS_OF_IMPACT_OR_NA
Comment on lines +16 to +17
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The "AREAS OF IMPACT" section uses a free-text placeholder only, which may lead to vague or missing impact descriptions.

Why: Clear, structured impact information helps reviewers quickly understand risk and affected components; unstructured text can be inconsistent and less useful.

How to Fix: Provide examples or a suggested format (e.g., bullet list or component names) to guide authors toward more actionable impact descriptions.

Suggested change
## AREAS OF IMPACT
REPLACE_ME_WITH_AREAS_OF_IMPACT_OR_NA
## AREAS OF IMPACT
REPLACE_ME_WITH_AREAS_OF_IMPACT_OR_NA
<!-- Example: Billing API, Invoicing UI, Webhooks, Reporting, Docs -->


## TYPE OF CHANGE
- [ ] 🐞 Bugfix
- [ ] 🌟 Feature
- [ ] ✨ Enhancement
- [ ] 🧪 Unit Test Cases
- [ ] 📔 Documentation
- [ ] ⚙️ Chore - Build Related / Configuration / Others
Comment on lines +19 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The "TYPE OF CHANGE" section uses emojis, which may not render consistently in all environments and can be noisy for any future automated parsing.

Why: While emojis are visually helpful, they can hinder machine readability and may not be accessible in all contexts (e.g., screen readers or text-only views).

How to Fix: Keep the labels but move emojis to comments or remove them, ensuring the primary information is plain text.

Suggested change
## TYPE OF CHANGE
- [ ] 🐞 Bugfix
- [ ] 🌟 Feature
- [ ] Enhancement
- [ ] 🧪 Unit Test Cases
- [ ] 📔 Documentation
- [ ] ⚙️ Chore - Build Related / Configuration / Others
## TYPE OF CHANGE
- [ ] Bugfix
- [ ] Feature
- [ ] Enhancement
- [ ] Unit Test Cases
- [ ] Documentation
- [ ] Chore - Build Related / Configuration / Others



## DOCUMENTATION
REPLACE_ME_WITH_DOCUMENTATION_LINK_OR_NA
Comment on lines +28 to +29
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The file has no trailing newline (\n), as indicated by \ No newline at end of file.

Why: Many tools and linters expect a trailing newline at the end of text files; missing it can cause unnecessary diffs and minor tooling issues.

How to Fix: Add a newline at the end of the file.

Suggested change
## DOCUMENTATION
REPLACE_ME_WITH_DOCUMENTATION_LINK_OR_NA
## DOCUMENTATION
REPLACE_ME_WITH_DOCUMENTATION_LINK_OR_NA

31 changes: 31 additions & 0 deletions .github/scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Scripts

## Generate changelog

Lists PRs merged into a branch (excludes "Parent branch sync" and bot-authored PRs).

**Prerequisites:** `jq`, and GitHub credentials as env vars.

### Set credentials (once per terminal)

```bash
export GH_USERNAME=your-github-username
export GH_PAT=your-github-personal-access-token
```

### Commands

From repo root:

| What you want | Command |
|---------------|---------|
| PRs merged into **current branch** (last 30 days) | `./.github/scripts/generate-changelog.sh` |
| PRs merged into **master** (last 30 days) | `./.github/scripts/generate-changelog.sh master` |
| PRs merged into **master** since a date | `./.github/scripts/generate-changelog.sh master "merged:>=2025-01-01"` |

### Arguments

1. **Branch** (optional) — default: current branch
2. **Date filter** (optional) — default: last 30 days (e.g. `merged:>=2025-01-01`)

Output includes a GitHub search URL to verify results.
84 changes: 84 additions & 0 deletions .github/scripts/generate-changelog.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash

set -e

# Check required environment variables
if [[ -z "$GH_USERNAME" ]]; then
echo "❌ Error: Environment variable GH_USERNAME not found"
exit 1
fi

if [[ -z "$GH_PAT" ]]; then
echo "❌ Error: Environment variable GH_PAT not found"
exit 1
fi

# Optional: Branch name (defaults to current branch if not provided)
SOURCE_BRANCH="${1:-$(git branch --show-current)}"
# Optional: Date filter (defaults to last 30 days if not provided)
DATE_FILTER="${2:-merged:>=$(date -u -v-30d +%Y-%m-%d 2>/dev/null || date -u -d '30 days ago' +%Y-%m-%d)}"

# Repo is set per-repo when this file is pushed (placeholder replaced by upload script)
REPO="chargebee/chargebee-flutter"
Comment on lines +18 to +22
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟠 HIGH

Problem: The DATE_FILTER default uses date -v-30d (BSD/macOS) with a fallback to date -d '30 days ago' (GNU/Linux), but the || fallback is inside the command substitution, so on systems where the first date variant exists but fails for another reason (e.g., locale/format issues), the whole script will still exit due to set -e and never reach the fallback.

Why: This makes the script brittle and potentially non-portable across environments; a transient failure in the first date invocation will cause the entire script to exit instead of gracefully trying the alternative, which is especially problematic for CI or shared tooling.

How to Fix: Move the fallback logic outside the command substitution and explicitly try BSD-style date first, then GNU-style date, and finally exit with a clear error if both fail, so set -e does not prevent the fallback from running.

Suggested change
# Optional: Date filter (defaults to last 30 days if not provided)
DATE_FILTER="${2:-merged:>=$(date -u -v-30d +%Y-%m-%d 2>/dev/null || date -u -d '30 days ago' +%Y-%m-%d)}"
# Repo is set per-repo when this file is pushed (placeholder replaced by upload script)
REPO="chargebee/chargebee-flutter"
# Optional: Date filter (defaults to last 30 days if not provided)
if [[ -z "$2" ]]; then
if DATE_VALUE=$(date -u -v-30d +%Y-%m-%d 2>/dev/null); then
DATE_FILTER="merged:>=$DATE_VALUE"
elif DATE_VALUE=$(date -u -d '30 days ago' +%Y-%m-%d 2>/dev/null); then
DATE_FILTER="merged:>=$DATE_VALUE"
else
echo "❌ Error: Unable to compute date 30 days ago with 'date' command"
exit 1
fi
else
DATE_FILTER="$2"
fi
# Repo is set per-repo when this file is pushed (placeholder replaced by upload script)
REPO="chargebee/chargebee-flutter"


echo "🔍 Searching for PRs merged into $SOURCE_BRANCH..."

# GitHub API call with error handling
HTTP_STATUS=$(curl -s -w "%{http_code}" -G -u "$GH_USERNAME:$GH_PAT" \
"https://api.github.com/search/issues" \
--data-urlencode "q=NOT \"Parent branch sync\" in:title is:pr repo:$REPO is:merged base:$SOURCE_BRANCH merged:$DATE_FILTER -author:app/distributed-gitflow-app" \
-o /tmp/curl_output.json \
2>/tmp/curl_error.log)

CURL_EXIT_CODE=$?

echo "🌐 API call status: $HTTP_STATUS"

if [ $CURL_EXIT_CODE -ne 0 ]; then
echo "❌ Error: curl request failed with exit code $CURL_EXIT_CODE"
echo "Error details: $(cat /tmp/curl_error.log)"
exit 1
fi

if [ "$HTTP_STATUS" -ne 200 ]; then
echo "❌ Error: API returned HTTP status $HTTP_STATUS"
echo "Response: $(cat /tmp/curl_output.json)"
exit 1
fi

PR_LIST_RESPONSE=$(cat /tmp/curl_output.json)
Comment on lines +35 to +49
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟡 MEDIUM

Problem: The script logs the full HTTP status line (🌐 API call status: $HTTP_STATUS), which includes the numeric status code but not the request URL or query; however, the subsequent error message on non-200 responses prints the entire JSON response inline, which can be very large and noisy for users.

Why: Dumping the full JSON response directly to stdout on error can make it hard to see the actual error cause, especially if the response contains many items; it also makes logs harder to scan and may expose more data than necessary in CI logs.

How to Fix: Print a concise error summary (status code and message) and write the full JSON response to a temporary debug file, similar to how invalid JSON is handled later, so users can inspect details only when needed.

Suggested change
echo "🌐 API call status: $HTTP_STATUS"
if [ $CURL_EXIT_CODE -ne 0 ]; then
echo "❌ Error: curl request failed with exit code $CURL_EXIT_CODE"
echo "Error details: $(cat /tmp/curl_error.log)"
exit 1
fi
if [ "$HTTP_STATUS" -ne 200 ]; then
echo "❌ Error: API returned HTTP status $HTTP_STATUS"
echo "Response: $(cat /tmp/curl_output.json)"
exit 1
fi
PR_LIST_RESPONSE=$(cat /tmp/curl_output.json)
echo "🌐 API call status: $HTTP_STATUS"
if [ $CURL_EXIT_CODE -ne 0 ]; then
echo "❌ Error: curl request failed with exit code $CURL_EXIT_CODE"
echo "Error details: $(cat /tmp/curl_error.log)"
exit 1
fi
if [ "$HTTP_STATUS" -ne 200 ]; then
cp /tmp/curl_output.json /tmp/changelog_api_error.json 2>/dev/null || true
echo "❌ Error: API returned HTTP status $HTTP_STATUS"
echo "💡 Full response saved to /tmp/changelog_api_error.json for inspection"
exit 1
fi
PR_LIST_RESPONSE=$(cat /tmp/curl_output.json)


# Clean invalid control characters from JSON response
if ! echo "$PR_LIST_RESPONSE" | jq . >/dev/null 2>&1; then
echo "⚠️ Invalid JSON detected — cleaning control characters..."
PR_LIST_RESPONSE=$(echo "$PR_LIST_RESPONSE" | tr -d '\000-\037')

if ! echo "$PR_LIST_RESPONSE" | jq . >/dev/null 2>&1; then
echo "$PR_LIST_RESPONSE" > /tmp/invalid_json_debug.json
echo "❌ Error: JSON is still invalid after cleaning control characters"
echo "💡 Use 'cat /tmp/invalid_json_debug.json' to inspect the JSON"
exit 1
fi
fi

PR_MERGED_COUNT=$(echo "$PR_LIST_RESPONSE" | jq '.total_count')

# Color codes
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NOCOLOR='\033[0m'

echo "=============================================================================="
echo -e "Found ${GREEN}$PR_MERGED_COUNT${NOCOLOR} PR(s) merged into $SOURCE_BRANCH (filter: $DATE_FILTER)"
echo "=============================================================================="
echo -e "## ${GREEN}CHANGELOG${NOCOLOR}"
echo "$PR_LIST_RESPONSE" | jq -r '.items[] | (.title) + " (" + (.user.login) + ") [#" + (.number | tostring) + "]"' | sort
printf "\n"
Comment on lines +71 to +76
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟡 MEDIUM

Problem: The script assumes that .items exists and is an array when piping to jq -r '.items[] | ...', but it does not guard against the case where .items is missing or not an array (e.g., unexpected API response shape), which would cause jq to exit non-zero and terminate the script due to set -e.

Why: A schema change or partial API failure could result in a different JSON structure, causing the script to crash instead of failing gracefully with a clear message; this reduces robustness of the tooling.

How to Fix: Add a defensive check that .items is an array before iterating, and if not, print a clear error and exit, or handle the empty/non-array case gracefully.

Suggested change
echo "=============================================================================="
echo -e "Found ${GREEN}$PR_MERGED_COUNT${NOCOLOR} PR(s) merged into $SOURCE_BRANCH (filter: $DATE_FILTER)"
echo "=============================================================================="
echo -e "## ${GREEN}CHANGELOG${NOCOLOR}"
echo "$PR_LIST_RESPONSE" | jq -r '.items[] | (.title) + " (" + (.user.login) + ") [#" + (.number | tostring) + "]"' | sort
printf "\n"
echo "=============================================================================="
echo -e "Found ${GREEN}$PR_MERGED_COUNT${NOCOLOR} PR(s) merged into $SOURCE_BRANCH (filter: $DATE_FILTER)"
echo "=============================================================================="
echo -e "## ${GREEN}CHANGELOG${NOCOLOR}"
if echo "$PR_LIST_RESPONSE" | jq -e '.items | type == "array"' >/dev/null 2>&1; then
echo "$PR_LIST_RESPONSE" | jq -r '.items[] | (.title) + " (" + (.user.login) + ") [#" + (.number | tostring) + "]"' | sort
else
echo "⚠️ Unexpected API response format: '.items' is missing or not an array"
fi
printf "\n"

echo "=============================================================================="
echo -e "${GREEN}GitHub Search URL (to verify, if required)${NOCOLOR}"
BRANCH_ENCODED=$(echo "$SOURCE_BRANCH" | sed 's/ /%20/g')
echo "https://github.com/$REPO/pulls?q=NOT+%22Parent+branch+sync%22+in%3Atitle+is%3Apr+is%3Amerged+base%3A$BRANCH_ENCODED+merged%3A$DATE_FILTER+-author%3Aapp%2Fdistributed-gitflow-app"
echo "=============================================================================="
Comment on lines +77 to +81
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The branch name is URL-encoded only for spaces (sed 's/ /%20/g'), but other characters that are valid in branch names (e.g., #, +, /) are not encoded, which can produce an invalid or misleading GitHub search URL.

Why: An incorrectly encoded URL may not reproduce the same search results in the browser, reducing the usefulness of the “GitHub Search URL” verification link, especially for branches with special characters.

How to Fix: Use a more robust URL-encoding approach for the branch name, for example by leveraging python -c or perl to percent-encode all non-safe characters.

Suggested change
echo "=============================================================================="
echo -e "${GREEN}GitHub Search URL (to verify, if required)${NOCOLOR}"
BRANCH_ENCODED=$(echo "$SOURCE_BRANCH" | sed 's/ /%20/g')
echo "https://github.com/$REPO/pulls?q=NOT+%22Parent+branch+sync%22+in%3Atitle+is%3Apr+is%3Amerged+base%3A$BRANCH_ENCODED+merged%3A$DATE_FILTER+-author%3Aapp%2Fdistributed-gitflow-app"
echo "=============================================================================="
echo "=============================================================================="
echo -e "${GREEN}GitHub Search URL (to verify, if required)${NOCOLOR}"
BRANCH_ENCODED=$(python - <<'PYCODE'
import sys, urllib.parse
print(urllib.parse.quote(sys.argv[1], safe=''))
PYCODE
"$SOURCE_BRANCH")
echo "https://github.com/$REPO/pulls?q=NOT+%22Parent+branch+sync%22+in%3Atitle+is%3Apr+is%3Amerged+base%3A$BRANCH_ENCODED+merged%3A$DATE_FILTER+-author%3Aapp%2Fdistributed-gitflow-app"
echo "=============================================================================="


# Clean up temporary files
rm -f /tmp/curl_output.json /tmp/curl_error.log
13 changes: 13 additions & 0 deletions .github/workflows/pr-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Common PR Lint

on:
pull_request:
branches: [master, main,staging, dev,develop]
types: [ready_for_review, reopened, review_requested, review_request_removed, opened, edited]

jobs:
Comment on lines +4 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: The types list for the pull_request trigger omits the synchronize event, so PR lint checks will not rerun when commits are pushed to an existing PR.

Why: Without handling synchronize, changes pushed after initial PR creation (e.g., addressing review comments) will not trigger the lint workflow, potentially allowing regressions or missing required checks on updated code.

How to Fix: Add synchronize to the types array so that the workflow runs whenever new commits are pushed to an open pull request.

Suggested change
pull_request:
branches: [master, main,staging, dev,develop]
types: [ready_for_review, reopened, review_requested, review_request_removed, opened, edited]
jobs:
pull_request:
branches: [master, main,staging, dev,develop]
types: [ready_for_review, reopened, review_requested, review_request_removed, opened, edited, synchronize]
jobs:

pr-lint:
name: Common PR Lint Checks
if: github.base_ref == 'main' || github.base_ref == 'master'
uses: chargebee/cb-cicd-pipelines/.github/workflows/pr-lint.yml@main
Comment on lines +3 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟡 MEDIUM

Problem: The branches list in the pull_request trigger includes staging, dev, and develop, but the job is hard-filtered to only run when github.base_ref is main or master, making those extra branches misleading and unnecessary.

Why: Having branches in the trigger that can never satisfy the job condition can confuse maintainers about which branches are actually linted and may lead to incorrect assumptions about coverage; it also adds noise to the workflow configuration.

How to Fix: Either remove the unused branches from the trigger to reflect the actual behavior, or, if linting is desired on those branches, update the if condition to include them so the job runs as expected.

Suggested change
on:
pull_request:
branches: [master, main,staging, dev,develop]
types: [ready_for_review, reopened, review_requested, review_request_removed, opened, edited]
jobs:
pr-lint:
name: Common PR Lint Checks
if: github.base_ref == 'main' || github.base_ref == 'master'
uses: chargebee/cb-cicd-pipelines/.github/workflows/pr-lint.yml@main
on:
pull_request:
branches: [master, main]
types: [ready_for_review, reopened, review_requested, review_request_removed, opened, edited]
jobs:
pr-lint:
name: Common PR Lint Checks
if: github.base_ref == 'main' || github.base_ref == 'master'
uses: chargebee/cb-cicd-pipelines/.github/workflows/pr-lint.yml@main

secrets: inherit
81 changes: 81 additions & 0 deletions .github/workflows/pr-size-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: PR Size Check
on:
pull_request:
types: [ reopened, opened, synchronize, edited, labeled, unlabeled ]
branches:
- main


jobs:
pre-approval-comment:
name: Announce pending bypass approval
if: ${{ github.event.pull_request.user.login != 'distributed-gitflow-app[bot]' &&
!startsWith(github.head_ref, 'revert-') &&
!startsWith(github.head_ref, 'parent-branch-sync/') &&
contains(github.event.pull_request.labels.*.name, 'pr-size-exception') }}
runs-on: graviton-small-runner
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const issue_number = context.payload.pull_request.number;

const marker = '<!-- pr-size-bypass-pending -->';
const pending = `${marker}
🛑 The \`pr-size-exception\` label is present. This workflow is **waiting for approvals** from the **[cb-Billing-CAB-reviewers](https://github.com/orgs/chargebee/teams/cb-billing-cab-approvers)**.`;

// create a new comment when the workflow runs
await github.rest.issues.createComment({ owner, repo, issue_number, body: pending });
Comment on lines +21 to +34
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟠 HIGH

Problem: The pre-approval-comment job runs on every qualifying event with the pr-size-exception label and always posts a new comment, which will spam the PR with duplicate “pending bypass approval” comments.

Why: On every synchronize, edited, labeled, unlabeled, or reopened event while the label is present, this job will add another identical comment, cluttering the PR discussion and making it harder to track real reviewer feedback.

How to Fix: Before creating a new comment, query existing comments for the marker (<!-- pr-size-bypass-pending -->) and only create a comment if one does not already exist.

Suggested change
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const issue_number = context.payload.pull_request.number;
const marker = '<!-- pr-size-bypass-pending -->';
const pending = `${marker}
🛑 The \`pr-size-exception\` label is present. This workflow is **waiting for approvals** from the **[cb-Billing-CAB-reviewers](https://github.com/orgs/chargebee/teams/cb-billing-cab-approvers)**.`;
// create a new comment when the workflow runs
await github.rest.issues.createComment({ owner, repo, issue_number, body: pending });
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const issue_number = context.payload.pull_request.number;
const marker = '<!-- pr-size-bypass-pending -->';
const pending = `${marker}
🛑 The \`pr-size-exception\` label is present. This workflow is **waiting for approvals** from the **[cb-Billing-CAB-reviewers](https://github.com/orgs/chargebee/teams/cb-billing-cab-approvers)**.`;
// Check if a pending marker comment already exists
const { data: comments } = await github.rest.issues.listComments({
owner,
repo,
issue_number,
per_page: 100,
});
const alreadyPending = comments.some(comment => comment.body && comment.body.includes(marker));
if (!alreadyPending) {
await github.rest.issues.createComment({ owner, repo, issue_number, body: pending });
}

pr-size-check:
name: Check PR size
if: ${{ (github.base_ref == 'main') && github.event.pull_request.user.login != 'distributed-gitflow-app[bot]' && !startsWith(github.head_ref, 'revert-') && !startsWith(github.head_ref, 'parent-branch-sync/') }}
runs-on: graviton-small-runner
permissions:
contents: read
pull-requests: write
id-token: write
env:
BYPASS_LABEL: pr-size-exception
environment: ${{ contains(github.event.pull_request.labels.*.name, 'pr-size-exception') && 'cb-billing-reviewers' || '' }}
steps:
- uses: chargebee/cb-cicd-pipelines/.github/actions/pr-size-check@v4.20.3
Comment on lines +43 to +47
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟡 MEDIUM

Problem: The environment is set to an empty string when the pr-size-exception label is not present, which is not a valid environment name and may cause the job to fail or behave unexpectedly.

Why: GitHub Actions expects environment to be either omitted or set to a valid environment name; providing an empty string can lead to configuration errors or undefined behavior, especially if environments are used for protection rules.

How to Fix: Use a conditional expression that omits the environment when the label is not present by moving the condition into the job if or by splitting into two jobs, or use a separate job that only runs with the environment when the label is present. Within a single job, the safest approach is to remove environment and instead gate the OIDC/S3 steps on the label (which you already do).

Suggested change
env:
BYPASS_LABEL: pr-size-exception
environment: ${{ contains(github.event.pull_request.labels.*.name, 'pr-size-exception') && 'cb-billing-reviewers' || '' }}
steps:
- uses: chargebee/cb-cicd-pipelines/.github/actions/pr-size-check@v4.20.3
env:
BYPASS_LABEL: pr-size-exception
steps:
- uses: chargebee/cb-cicd-pipelines/.github/actions/pr-size-check@v4.20.3

if: ${{ !contains(github.event.pull_request.labels.*.name, env.BYPASS_LABEL) }}
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
errorSize: 250
warningSize: 200
excludePaths: |
.github/**
.cursor/**


- name: Ensure required check passes when bypassed
Comment on lines +53 to +58
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟢 LOW

Problem: There are two consecutive blank lines in the excludePaths block, which is minor formatting noise and can be confusing when scanning the workflow.

Why: Extra blank lines inside YAML blocks can make the configuration look untidy and, in some editors or linters, may be flagged as style issues, slightly reducing readability.

How to Fix: Remove the redundant blank lines so that the excludePaths list is compact and consistent.

Suggested change
excludePaths: |
.github/**
.cursor/**
- name: Ensure required check passes when bypassed
excludePaths: |
.github/**
.cursor/**
- name: Ensure required check passes when bypassed

if: ${{ contains(github.event.pull_request.labels.*.name, env.BYPASS_LABEL) }}
run: echo "Bypass active — marking job successful."

- name: Configure OIDC authentication
if: ${{ contains(github.event.pull_request.labels.*.name, env.BYPASS_LABEL) }}
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::127322177288:role/OIDC_S3
role-session-name: GithubActionsSession
role-duration-seconds: 900
aws-region: us-east-1

- name: Record bypass approval to S3
if: ${{ contains(github.event.pull_request.labels.*.name, env.BYPASS_LABEL) }}
run: |
REPO="${{ github.repository }}"
PR_LINK="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
WF_ID="${{ github.run_id }}"
S3_KEY="${REPO}/datas/${WF_ID}.json"
printf '{"repo":"%s","date":"%s","pr_link":"%s","wf_id":"%s"}\n' "$REPO" "$DATE" "$PR_LINK" "$WF_ID" | \
aws s3 cp - "s3://prsizebypassdata/${S3_KEY}" --content-type application/json
echo "Recorded to s3://prsizebypassdata/${S3_KEY}"
Comment on lines +71 to +81
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Priority: 🟡 MEDIUM

Problem: The S3 key and bucket name used to record bypass approvals are hard-coded (prsizebypassdata and datas), which makes this workflow less portable and harder to adjust across environments or repositories.

Why: Hard-coded infrastructure identifiers couple the workflow tightly to a specific AWS setup; any change to bucket naming, prefixes, or multi-environment support will require code changes instead of configuration changes, increasing maintenance overhead and risk of misconfiguration.

How to Fix: Move the bucket name and (optionally) the prefix into workflow-level env variables or repository/organization secrets, and reference those variables in the script so they can be updated without modifying the workflow logic.

Suggested change
- name: Record bypass approval to S3
if: ${{ contains(github.event.pull_request.labels.*.name, env.BYPASS_LABEL) }}
run: |
REPO="${{ github.repository }}"
PR_LINK="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
WF_ID="${{ github.run_id }}"
S3_KEY="${REPO}/datas/${WF_ID}.json"
printf '{"repo":"%s","date":"%s","pr_link":"%s","wf_id":"%s"}\n' "$REPO" "$DATE" "$PR_LINK" "$WF_ID" | \
aws s3 cp - "s3://prsizebypassdata/${S3_KEY}" --content-type application/json
echo "Recorded to s3://prsizebypassdata/${S3_KEY}"
- name: Record bypass approval to S3
if: ${{ contains(github.event.pull_request.labels.*.name, env.BYPASS_LABEL) }}
env:
PR_SIZE_BYPASS_BUCKET: prsizebypassdata
PR_SIZE_BYPASS_PREFIX: datas
run: |
REPO="${{ github.repository }}"
PR_LINK="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
WF_ID="${{ github.run_id }}"
S3_KEY="${REPO}/${PR_SIZE_BYPASS_PREFIX}/${WF_ID}.json"
printf '{"repo":"%s","date":"%s","pr_link":"%s","wf_id":"%s"}\n' "$REPO" "$DATE" "$PR_LINK" "$WF_ID" | \
aws s3 cp - "s3://${PR_SIZE_BYPASS_BUCKET}/${S3_KEY}" --content-type application/json
echo "Recorded to s3://${PR_SIZE_BYPASS_BUCKET}/${S3_KEY}"

Loading