Skip to content

GitHub Actions

Tahmid Ahmed edited this page Jan 8, 2026 · 8 revisions

Workflow Actions

CI/CD

This is the main CI/CD file which is responsible for the following:

Jobs

  • Verify PR against Notion (only runs on pull requests)
    • Parse the numeric prefix from the PR title (e.g., "516" from "516: Add new feature")
    • Query Notion API to verify the task ID exists in the Notion task database
    • If the task doesn't exist, post a comment on the PR and fail the check
    • If the task exists, update the PR description with a link to the Notion task
    • Update the Notion task with a link to the PR
  • Running backend tests
    • Compilation test
    • Run Checkstyle for formatting
    • Run automated tests using the ci profile
    • Generate a test coverage report as a PR comment
  • Running frontend tests
    • This includes linting, styling, formatting, typechecks, and more
  • Test build a Docker image
    • This will not be uploaded to the registry

      If you would like to test a deployment, you may refer to Deploy to staging

  • Validate database schema
    • This task will log into the production-ro user in the production database and ensure that no previous database schemas were changed or modified in anyway that will cause a schema drift.

      This will NOT migrate the production database.

The following jobs will only run once merged into the main branch:

  • Build Docker image
    • This will be uploaded to the registry and marked under the latest tag for production.
  • Redeploy to DigitalOcean, which does the following:
    • Migrate the production database if there are any new migrations
    • Transform the production app spec (read more about our DigitalOcean integration here by adding all environment secrets from .env.production
    • Trigger a brand new redeployment, and keep polling the DO API until the deployment reaches the ACTIVE state.

Implementation

You can find the implementation here at .github/workflows/ci-cd.yml

Deploying to staging

This actions allows developers to deploy to our shared staging environment at stg.codebloom.patinanetwork.org.

Jobs

  • Send a message to the PR that triggered the deployment indicating that the process to stage deployment has started
  • If the staging image has been built before under staging-{sha}, promote that image to be staging-latest and skip ahead to the redeployment job.
  • Running backend tests
    • Compilation test
    • Run Checkstyle for formatting
    • Run automated tests using the ci profile
    • Generate a test coverage report as a PR comment
  • Running frontend tests
    • This includes linting, styling, formatting, typechecks, and more
  • Build a Docker image
    • This will be uploaded to the registry staging-latest for deployment
  • Validate database schema
    • This task will log into the staging-ro user in the staging database and ensure that no previous database schemas were changed or modified in anyway that will cause a schema drift.

      This will NOT migrate the staging database.

  • Redeploy to DigitalOcean, which does the following:
    • Migrate the staging database if there are any new migrations
    • Transform the staging app spec (read more about our DigitalOcean integration here by adding all environment secrets from .env.staging
    • Trigger a brand new redeployment, and keep polling the DO API until the deployment reaches the ACTIVE state.

How to trigger deployment

All PRs must be tested in our staging environment to make sure that it won’t break anything (if there’s a reason it cannot be tested in staging, it must be indicated in the PR description).

To trigger deployment to staging, you just have to comment /deploy as a comment in the PR.

Note

It should be a regular comment inside of the first page of the PR; writing the command as a review on a file or line(s) will not trigger deployment.

Gotchas during development

Warning

If you make a PR with changes to deploy-stg.yaml inside of PR, it will not use the new changes. That's because repository_dispatch (slash command trigger) will only use the latest changes from the main branch. However, there is a solution: on your local machine you can run ci-test-stg {pr_name} {pr_id}. However, this command has some gotchas so please reach out to @tahminator to help you utilizing the command.

Implementation

You can find the implementation at .github/workflows/slash.yml.

PR Verifications

This workflow runs on every pull request to verify that it meets the project's standards. It performs the following checks:

  • Runs the Check Notion PR composite action to verify the PR is linked to a valid Notion task
  • Runs the Check Notion Commits composite action to verify all commits follow the Notion task ID prefix convention

This workflow runs separately from the main CI/CD workflow to provide faster feedback on PR metadata issues.

Implementation

You can find the implementation at .github/workflows/pr-verifications.yml.

AI Code Review

This workflow provides automated AI-powered code review for pull requests using Qodo PR-Agent.

Triggers

The workflow runs automatically on:

  • Pull request opened
  • Pull request reopened
  • Pull request marked as ready for review

It can also be triggered manually via slash commands in PR comments.

Slash Commands

  • /review - Triggers an AI review of the PR changes
  • /describe - Generates an AI-powered description of the PR
  • /improve - Provides AI-powered code improvement suggestions

The AI review integrates with Notion by including task context in the review, ensuring the implementation matches acceptance criteria.

Implementation

You can find the implementation at .github/workflows/ai-review.yml.

AI Command Handler

This workflow handles the /ai slash command dispatched from PRs. When triggered, it posts the following commands as comments on the PR to trigger the AI Code Review workflow:

  • /review
  • /describe
  • /improve

This allows triggering all AI review features with a single /ai command.

Implementation

You can find the implementation at .github/workflows/ai-command.yml.

Approvals

Caution

This is currently deprecated/disabled until further notice.

Approvals is a custom GitHub Action that defines custom behaviors for approvals. For example, we have a two-step approval process:

Step 1) Get preliminary review & approval by angelayu0530 Step 2) Get Final review & approval by tahminator

This action allows us to do that by calculating how many approvals are needed (or no longer needed) and push a new check to the PR indicating it's status.

Examples

image image

Implementation

You can find the implementation at .github/workflows/approval.yml.

Composite Actions

Load Secrets

This composite action can be used to decrypt secrets and load them into the environment for the given job (as well as mask all secrets to avoid accidental leakages).

Implementation

The full implementation can be found in .github/composite/load-secrets/action.yml

Example

            - name: Load secrets
              uses: ./.github/composite/load-secrets
              with:
                GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
                GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
                UNLOAD_ENVIRONMENTS: ci,production # will load .env.ci, .env.production

            - name: Install doctl
              uses: digitalocean/action-doctl@v2
              with:
                token: ${{ env.DIGITAL_OCEAN_PAT }} # loaded from the previous action

Check Notion PR

This composite action verifies that a PR is associated with a valid Notion task ID. It performs the following:

  • Parses the numeric prefix from the PR title (e.g., "516" from "516: Add new feature")
  • Queries the Notion API to verify the task ID exists in the configured Notion task database
  • If the task doesn't exist:
    • Posts a comment on the PR notifying the author
    • Fails the check to prevent merging
  • If the task exists:
    • Updates the PR description with a clickable link to the Notion task
    • Updates the Notion task's "PRs (AUTO)" field with a link to the PR

Implementation

The full implementation can be found in .github/composite/check-notion-pr/action.yml

Example

- name: Run 'Check Notion PR' composite action
  uses: ./.github/composite/check-notion-pr
  with:
    PR_ID: ${{ github.event.number }}
    GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
    GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}

Check Notion Commits

This composite action verifies that all commits in a PR follow the Notion task ID prefix convention. It performs the following:

  • Extracts all commit messages from the PR
  • Validates that each commit message starts with a valid Notion task ID prefix (e.g., "533: Commit message")
  • If any commits don't follow the convention or reference invalid task IDs:
    • Posts a comment on the PR notifying the author
    • Fails the check to prevent merging

Note

This task does not need to make any network requests to Notion. This is because we can receive the ticket ID from Check Notion PR.

This composite action is called by the "Check Notion PR" workflow to ensure all commits maintain proper traceability to Notion tasks.

Implementation

The full implementation can be found in .github/composite/check-notion-commits/action.yml

Example

- name: Run 'Check Notion Commits' composite action
  uses: ./.github/composite/check-notion-commits
  with:
    PR_ID: ${{ github.event.number }}
    NOTION_ID: ${{ steps.check-notion-pr.outputs.notion_id }}
    GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
    GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}

Send Message

This composite action posts an arbitrary message as a comment to a pull request. It's used by other composite actions (like Check Notion PR and Check Notion Commits) to communicate with PR authors.

Implementation

The full implementation can be found in .github/composite/send-message/action.yml

Example

- name: Send a message to the PR
  uses: ./.github/composite/send-message
  with:
    prId: ${{ github.event.number }}
    message: |
      Task ID does not exist on Notion. Please set a valid Notion task ID to the start of the PR title.

Disable man-db

This composite action disables the man-db auto-update triggers on Ubuntu runners to speed up CI time. Package installations that would normally trigger man-db updates will skip this step.

Implementation

The full implementation can be found in .github/composite/disable-mandb/action.yml

Backend Pre Test

This composite action runs backend linting, formatting checks, and compilation without running the full test suite. It's used for fast feedback on code quality issues.

The action performs:

  • Disables man-db to speed up CI
  • Sets up OpenJDK 25 with Maven caching
  • Runs Spotless formatting check
  • Runs Checkstyle linting
  • Compiles the project (skipping tests)

Implementation

The full implementation can be found in .github/composite/test/backend-pre-test/action.yml

Example

- name: Run backend pre-test checks
  uses: ./.github/composite/test/backend-pre-test

Scripts

These scripts are used within CI to help share logic between actions.

While you may run these scripts on your local machine, their behavior may be unexpected depending on your OS or your environment. If you need help running these scripts locally, please reach out to @tahminator.

build-image.sh

This script is used to build and optionally push Docker images for the application. It:

  • Sets up the local database and backend instance for testing
  • Runs frontend tests to ensure code quality
  • Builds multi-platform Docker images with multiple tags (latest, timestamp, git SHA)
  • Can either push to registry or load locally based on DOCKER_UPLOAD environment variable
  • Requires DOCKER_HUB_PAT for authentication

Implementation

You can find the implementation at .github/scripts/build-image.sh.

load-secrets.sh

This script loads encrypted environment variables from specified .env files and makes them available to GitHub Actions:

  • Unlocks git-crypt to access encrypted files
  • Loads environment variables from files specified in UNLOAD_ENVIRONMENTS
  • Automatically masks sensitive values in GitHub Actions logs
  • Excludes common system variables from masking (PATH, HOME, etc.)
  • Exports all loaded variables to $GITHUB_ENV

Implementation

You can find the implementation at .github/scripts/load-secrets.sh.

local-db.sh

This script provides functions for managing a local PostgreSQL database in Docker:

  • db_startup(): Creates and starts a PostgreSQL 16 container on port 5440
  • db_cleanup(): Stops and removes the database container
  • Automatically runs Flyway migrations after database startup
  • Sets appropriate environment variables for database connection
  • Includes health checks to ensure database is ready before proceeding

Implementation

You can find the implementation at .github/scripts/local-db.sh.

run-backend-compile-tests.sh

This script runs quick backend validation checks without the full test suite:

  • Runs Spotless formatting check (spotless:check)
  • Runs Checkstyle linting (checkstyle:check)
  • Compiles and verifies the project without running tests (verify -Dmaven.test.skip=true)

This is used by the Backend Pre Test composite action for fast feedback on code quality.

Implementation

You can find the implementation at .github/scripts/run-backend-compile-tests.sh.

run-backend-instance.sh

This script manages the Spring Boot backend application:

  • backend_startup(): Starts the backend with the ci profile in the background
  • backend_cleanup(): Stops the backend process and displays logs
  • Performs health checks by polling the /api endpoint
  • Logs all output to backend.log for debugging
  • Stores process ID for proper cleanup

Implementation

You can find the implementation at .github/scripts/run-backend-instance.sh.

run-backend-tests.sh

This comprehensive script runs the full backend test suite:

  • Compiles the application and runs Checkstyle formatting checks
  • Installs Playwright dependencies for browser testing
  • Sets up email service dependencies
  • Starts local database and runs all tests with the ci profile
  • Includes proper cleanup of all resources

Implementation

You can find the implementation at .github/scripts/run-backend-tests.sh.

run-frontend-tests.sh

This script runs the complete frontend test suite:

  • Sets up local database and backend instance
  • Installs frontend dependencies with pnpm
  • Generates TypeScript types from backend API
  • Runs all frontend tests including linting, styling, and unit tests
  • Ensures proper cleanup of all services

Implementation

You can find the implementation at .github/scripts/run-frontend-tests.sh.

transform-yaml-with-env.sh

This utility script transforms DigitalOcean app specs with environment variables:

  • Takes an app spec YAML file and environment file as input
  • Parses environment variables and converts them to DigitalOcean format
  • Sets all variables as secrets with RUN_AND_BUILD_TIME scope
  • Uses yq to safely modify YAML structure
  • Provides feedback on number of variables processed

Implementation

You can find the implementation at .github/scripts/transform-yaml-with-env.sh.

Clone this wiki locally