diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000..19f21ce --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,55 @@ +## ๐Ÿ“ Overview + +_What does this PR do? Briefly describe the changes and the goal of this PR._ + +## ๐Ÿš€ Type of Change + +- [ ] ๐Ÿ› **Bug Fix**: Fixed something that was broken. +- [ ] โœจ **New Feature**: Added new functionality or pages. +- [ ] ๐Ÿ—„๏ธ **CMS / Database**: Updated collections, fields, or config in Payload CMS. +- [ ] ๐Ÿงน **Chore / Clean up**: Text updates, typos, or code cleanup. + +--- + +## ๐Ÿงฑ CMS & Database Changes + +_Skip this section if no CMS or database changes were made._ + +- [ ] **Migration Created**: Ran `payload migrate:create` and saved the file. +- [ ] **Local Verification**: Verified changes in the local admin panel. + +### ๐Ÿ“Š Data Structure + +_Describe the new fields/tables or drag-and-drop a screenshot here:_ + +--- + +## ๐Ÿงช Testing & Validation + +- [ ] **Test Case Approval**: Verified that test cases were commented on the assigned GitHub issue and approved by the Project Lead _before_ development started. +- [ ] **Unit Tests**: Added or updated unit test scripts covering the new logic. +- [ ] **Admin Panel**: Verified behavior in the CMS Admin UI. +- [ ] **API Check**: Tested REST/GraphQL endpoints for correct data. + +### ๐Ÿ“ธ Visual Evidence (Mandatory) + +> [!IMPORTANT] +> Visual proof is required to demonstrate that the approved test cases from the issue were successfully met. +> Please provide screenshots, screen recordings (GIFs/Videos), or sample API outputs proving that the feature satisfies all approved test cases and do not introduce regressions. + +--- + +## ๐Ÿ“‹ Final Checklist + +- [ ] **Sync**: Rebased from `main` and resolved conflicts. +- [ ] **Pre-commit**: Installed and ran pre-commit hooks successfully. +- [ ] **Security**: Verified no secrets or local credentials are included. +- [ ] **Build**: Project builds without errors. +- [ ] **Visuals**: Attached mandatory visual evidence proving all test cases passed. +- [ ] **Migrations**: Migration script included (if applicable). + +--- + +## ๐Ÿง  Extra Notes / Questions + +_Add any additional context or questions for the reviewers here._ diff --git a/.github/PULL_REQUEST_TEMPLATE/release_production.md b/.github/PULL_REQUEST_TEMPLATE/release_production.md new file mode 100644 index 0000000..aceb4ca --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/release_production.md @@ -0,0 +1,31 @@ +## ๐Ÿš€ Production Release PR + +> [!IMPORTANT] > **Action Required**: You MUST apply one of the following labels to this PR in the GitHub sidebar before merging: +> +> - `release:major` (Breaking changes โ€” e.g., `1.0.0` โžก๏ธ `2.0.0`) +> - `release:minor` (New features / non-breaking schema additions โ€” e.g., `1.0.0` โžก๏ธ `1.1.0`) +> - `release:patch` (Bug fixes / chores โ€” e.g., `1.0.0` โžก๏ธ `1.0.1`) +> +> This label is required by the CD workflow to calculate the version bump and publish the release. + +--- + +## ๐Ÿ“ Release Summary + +_Briefly summarize the major changes included in this release._ + +## ๐Ÿ“Š Included Changes (from main) + +_List the features or fixes being promoted, or link to the PRs/Issues._ + +- [ ] Feature/Fix 1 (#PR-number) +- [ ] Feature/Fix 2 (#PR-number) + +--- + +## ๐Ÿ“‹ Release Checklist + +- [ ] **CI Validation**: Verify that the CI checks have passed on `main`. +- [ ] **PR Labels**: Applied the appropriate `release:major`, `release:minor`, or `release:patch` label to this PR. +- [ ] **Database Migrations**: Verified that any database migration scripts are tested and ready for production. +- [ ] **QA Approval**: Changes have been tested and verified in staging/dev environment. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 850b6ff..0000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,56 +0,0 @@ -## ๐Ÿ“ Overview - -_What does this PR do? Briefly describe the changes and the goal of this PR._ - -## ๐Ÿš€ Type of Change - -- [ ] ๐Ÿ› **Bug Fix**: Fixed something that was broken. -- [ ] โœจ **New Feature**: Added new functionality or pages. -- [ ] ๐Ÿ—„๏ธ **CMS / Database**: Updated collections, fields, or config in Payload CMS. -- [ ] ๐Ÿงน **Chore / Clean up**: Text updates, typos, or code cleanup. - ---- - -## ๐Ÿงฑ CMS & Database Changes - -_Skip this section if no CMS or database changes were made._ - -- [ ] **Migration Created**: Ran `payload migrate:create` and saved the file. -- [ ] **Local Verification**: Verified changes in the local admin panel. - -### ๐Ÿ“Š Data Structure - -_Describe the new fields/tables or drag-and-drop a screenshot here:_ - ---- - -## ๐Ÿงช Testing & Validation - -- [ ] **Test Case Approval**: Verified that test cases were commented on the assigned GitHub issue and approved by the Project Lead _before_ development started. -- [ ] **Unit Tests**: Added or updated unit test scripts covering the new logic. -- [ ] **Admin Panel**: Verified behavior in the CMS Admin UI. -- [ ] **API Check**: Tested REST/GraphQL endpoints for correct data. - -### ๐Ÿ“ธ Visual Evidence (Mandatory) - -> [!IMPORTANT] -> Visual proof is required to demonstrate that the approved test cases from the issue were successfully met. - -_Please provide screenshots, screen recordings (GIFs/Videos), or sample API outputs proving that the feature satisfies all approved test cases and do not introduce regressions._ - ---- - -## ๐Ÿ“‹ Final Checklist - -- [ ] **Sync**: Rebased from `main` and resolved conflicts. -- [ ] **Pre-commit**: Installed and ran pre-commit hooks successfully. -- [ ] **Security**: Verified no secrets or local credentials are included. -- [ ] **Build**: Project builds without errors. -- [ ] **Visuals**: Attached mandatory visual evidence proving all test cases passed. -- [ ] **Migrations**: Migration script included (if applicable). - ---- - -## ๐Ÿง  Extra Notes / Questions - -_Add any additional context or questions for the reviewers here._ diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 120000 index 0000000..83e9af9 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1 @@ +PULL_REQUEST_TEMPLATE/pull_request_template.md \ No newline at end of file diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..2ec4f71 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,41 @@ +changelog: + exclude: + labels: + - ignore-release + - duplicate + authors: + - github-actions[bot] + - dependabot[bot] + + categories: + - title: '๐Ÿš€ Features' + labels: + - feature + - feat + - enhancement + + - title: '๐Ÿ› Bug Fixes' + labels: + - bug + - fix + - hotfix + + - title: '๐Ÿ“– Documentation' + labels: + - documentation + - docs + + - title: 'โš™๏ธ Refactoring & Infrastructure' + labels: + - refactor + - chore + - ci + + - title: '๐Ÿ“ฆ Dependency Updates' + labels: + - dependencies + - dependency + + - title: '๐Ÿก Other Changes' + labels: + - '*' diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index f7c25c6..544b9a0 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,40 +1,37 @@ -name: CMS Continuous Delivery +name: Production CD Pipeline on: + push: + branches: + - release/production workflow_dispatch: + inputs: + bump_type: + description: 'SemVer bump type (used if manual run)' + required: true + default: 'patch' + type: choice + options: + - patch + - minor + - major permissions: id-token: write - contents: read + contents: write actions: read - security-events: write + pull-requests: read jobs: deploy: name: Build & Production Deploy - if: github.ref_name == 'production' runs-on: ubuntu-latest environment: production steps: - - name: Verify CI Workflow Completion - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - echo "Checking the status of the latest 'CMS Continuous Integration' run for branch '${{ github.ref_name }}'..." - conclusion=$(gh run list --workflow "CMS Continuous Integration" --branch "${{ github.ref_name }}" --limit 1 --json conclusion --jq '.[0].conclusion') - - if [ -z "$conclusion" ]; then - echo "โŒ No runs found for the CI workflow on branch '${{ github.ref_name }}'." - exit 1 - elif [ "$conclusion" != "success" ]; then - echo "โŒ The latest run of the CI workflow on branch '${{ github.ref_name }}' is not successful (status: $conclusion)." - exit 1 - fi - - echo "โœ… The latest CI workflow run completed successfully." - - name: Checkout Source Code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Authenticate to AWS uses: aws-actions/configure-aws-credentials@v4 @@ -62,6 +59,13 @@ jobs: mask-values: true recursive: true + - name: Determine and Apply Version Bump + id: version-bump + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUMP_TYPE_INPUT: ${{ github.event.inputs.bump_type }} + run: ./scripts/bump-version.sh + - name: Install Dependencies run: npm ci --legacy-peer-deps @@ -101,7 +105,7 @@ jobs: file: docker/lambda/Dockerfile load: true tags: | - ${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ github.sha }} + ${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ steps.version-bump.outputs.new_tag }} secrets: | payload_secret=${{ steps.ssm-param.outputs.PAYLOAD_SECRET }} database_url=${{ steps.ssm-param.outputs.DATABASE_URL }} @@ -113,37 +117,57 @@ jobs: AWS_DEFAULT_REGION=ap-southeast-1 ENVIRONMENT=production - - name: Codebase Scan (Vulnerabilities & Misconfigurations) - uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 - with: - scan-type: 'fs' - scan-ref: '.' - scanners: 'vuln,misconfig' - format: 'sarif' - output: 'trivy-results.sarif' - severity: 'CRITICAL,HIGH' - skip-files: '.env.ci-build' - - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: 'trivy-results.sarif' - - name: Push Image if: success() run: | - docker push ${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ github.sha }} + docker push ${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ steps.version-bump.outputs.new_tag }} - name: Summarize Build if: always() run: | echo "### ๐Ÿšข Deployment Summary" >> $GITHUB_STEP_SUMMARY - echo "Image: \`${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY - echo "Security Scan: Results uploaded to the GitHub Security tab." >> $GITHUB_STEP_SUMMARY + echo "Image: \`${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ steps.version-bump.outputs.new_tag }}\`" >> $GITHUB_STEP_SUMMARY - name: Deploy to AWS Lambda if: success() run: | aws lambda update-function-code \ --function-name durianpy-cms-prod \ - --image-uri ${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ github.sha }} + --image-uri ${{ steps.login-ecr.outputs.registry }}/durianpy-cms-prod:${{ steps.version-bump.outputs.new_tag }} + + - name: Commit and Push Version Bump and CHANGELOG + if: success() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NEW_TAG: ${{ steps.version-bump.outputs.new_tag }} + run: | + # 1. Generate release notes from GitHub API + echo "Generating release notes for $NEW_TAG..." + RELEASE_NOTES=$(gh release generate-notes --tag "$NEW_TAG" --target "release/production") + + # 2. Prepend notes to CHANGELOG.md + DATE_STR=$(date +%Y-%m-%d) + if [ -f CHANGELOG.md ]; then + echo -e "# Release $NEW_TAG ($DATE_STR)\n\n$RELEASE_NOTES\n\n$(cat CHANGELOG.md)" > CHANGELOG.md + else + echo -e "# Release $NEW_TAG ($DATE_STR)\n\n$RELEASE_NOTES" > CHANGELOG.md + fi + + # 3. Commit and push changes + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add package.json CHANGELOG.md + git commit -m "chore(release): bump version to $NEW_TAG and update CHANGELOG [skip ci]" + git push origin release/production + + - name: Create Git Tag and Release + if: success() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NEW_TAG: ${{ steps.version-bump.outputs.new_tag }} + run: | + echo "๐Ÿš€ Creating GitHub Release for $NEW_TAG..." + gh release create "$NEW_TAG" \ + --title "Release $NEW_TAG" \ + --generate-notes \ + --target "release/production" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2b274f..e2e5d7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CMS Continuous Integration +name: CI Pipeline on: pull_request: diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh new file mode 100755 index 0000000..03b024b --- /dev/null +++ b/scripts/bump-version.sh @@ -0,0 +1,51 @@ +#!/bin/bash +set -e + +# 1. Fetch the merged PR associated with this commit +PR_JSON=$(gh api repos/"$GITHUB_REPOSITORY"/commits/"$GITHUB_SHA"/pulls 2>/dev/null || echo "[]") +LABELS=$(echo "$PR_JSON" | jq -r '.[0].labels[].name' 2>/dev/null || echo "") + +# 2. Determine bump type +BUMP_TYPE="" +if [ -n "$BUMP_TYPE_INPUT" ]; then + BUMP_TYPE="$BUMP_TYPE_INPUT" + echo "Manual run input detected. Selected bump type: $BUMP_TYPE" +else + if echo "$LABELS" | grep -q "release:major"; then + BUMP_TYPE="major" + elif echo "$LABELS" | grep -q "release:minor"; then + BUMP_TYPE="minor" + elif echo "$LABELS" | grep -q "release:patch"; then + BUMP_TYPE="patch" + else + echo "โŒ Error: Pull Requests targeting release/production must have one of these labels: release:major, release:minor, or release:patch" + exit 1 + fi +fi + +echo "Selected bump type: $BUMP_TYPE" + +# 3. Find the latest released Git tag to base the bump on +git fetch --tags +LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") +echo "Latest release tag: $LATEST_TAG" + +# Clean tag version (remove 'v' prefix) +PREV_VERSION="${LATEST_TAG#v}" + +# Set package.json version to the latest tag version temporarily +node -e " + const pkg = require('./package.json'); + pkg.version = '$PREV_VERSION'; + require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n'); +" + +# 4. Bump version using npm +NEW_VERSION=$(npm version "$BUMP_TYPE" --no-git-tag-version) +TAG_NAME="$NEW_VERSION" +echo "New Version: $TAG_NAME" + +# Expose new tag for subsequent steps in GitHub Actions +if [ -n "$GITHUB_OUTPUT" ]; then + echo "new_tag=$TAG_NAME" >> "$GITHUB_OUTPUT" +fi