Updates to GitHub Actions Workflows#
The project has migrated from Yarn/Node.js to Bun as the JavaScript runtime and package manager, and now uses mise for managing development tool versions. All workflows, Dockerfiles, and setup instructions have been updated to use Bun and mise instead of Yarn and Node.js. The new workflows are defined in .github/workflows/CI.yml and .github/workflows/docker-deploy.yml.
The CI workflow includes jobs for security scanning with Brakeman, linting with Rubocop, linting the OpenAPI specification with vacuum, and running tests with PostgreSQL and Redis services. The workflow uses mise to install and pin all required development tools (Ruby, Bun, Just, etc.) as specified in .mise.toml. JavaScript dependencies are installed with Bun (bun install). Asset building and other project automation tasks are run via just recipes, which use Bun for JavaScript scripts. The workflow triggers on pull requests, pushes to the main and develop branches, and via workflow_call, which makes the CI workflow reusable by other workflows. This enables the CI pipeline to serve as a quality gate for deployment workflows. Code Climate Test Reporter integration is conditional on the presence of the CC_TEST_REPORTER_ID secret, ensuring coverage reporting only when configured.
The lint_api job runs after the security scan and validates the generated OpenAPI specification (swagger/v1/swagger.json) for conformance to OpenAPI 3.0 standards and quality best practices. It uses vacuum, an OpenAPI linter, with a custom ruleset (vacuum-ruleset.yaml) that disables rules conflicting with Rails conventions (such as snake_case properties and underscore paths). The command mise exec -- vacuum lint swagger/v1/swagger.json -r vacuum-ruleset.yaml -b ensures consistent API documentation quality.
Key changes:
- Bun replaces Yarn and npm for all JavaScript dependency management and scripts.
- mise manages all tool versions, ensuring consistent environments in CI and locally.
- All references to
yarn install,yarn upgrade, andnpmhave been replaced withbun install,bun update, andbun run. - The lockfile used is now
bun.lockbinstead ofyarn.lockorpackage-lock.json.
Docker Deployment Actions#
Docker deployment is handled in .github/workflows/docker-deploy.yml. This workflow triggers on tags matching v*, indicating versioned releases. The workflow first calls the CI workflow as a prerequisite job, ensuring that all security scans, linting, and tests pass before building and deploying Docker images. The needs: [ci] dependency enforces sequential execution: only after the CI pipeline completes successfully will the Docker image build proceed. This prevents deploying containers that haven't passed the full test suite.
The workflow uses mise to install all development tools (including Bun) and runs just install to set up dependencies. The Dockerfile now installs Bun directly as the JavaScript runtime, and uses bun install to install JavaScript dependencies. The workflow sets up QEMU for multi-platform builds, configures Docker Buildx, logs into the GitHub Container Registry (ghcr.io) using a secret token, extracts Docker image metadata, and builds and pushes the Docker image for both amd64 and arm64 platforms. The workflow uses the official Docker GitHub Actions for setup, build, and push steps, ensuring reproducible and multi-architecture images.
View Docker deployment workflow
Dependabot Dependency Grouping and Ignoring Major Releases#
Dependabot is configured in .github/dependabot.yml to automate dependency updates for GitHub Actions, devcontainers, Bundler, and Bun (npm ecosystem, but using Bun as the package manager). Updates are scheduled weekly, with limits on the number of open pull requests to avoid overwhelming maintainers.
Dependency grouping is used to combine related updates into a single pull request. For Bundler, groups include rails-bundler-security (for rack and rack-session), observability-dev (for bullet), and analytics-time (for groupdate). For Bun (npm), groups include build-tooling (for esbuild, postcss*, sass) and hotwire-front (for @hotwired/*).
Certain major releases are explicitly ignored. For example, major version updates for esbuild in the npm ecosystem are ignored. The rationale is to avoid the risk of breaking changes that can disrupt builds or runtime behavior. This approach allows the team to review and plan for major upgrades separately, reducing the risk of unexpected failures in CI or production.
Note: The project uses Bun as the only supported JavaScript package manager. The lockfile is bun.lockb, and all dependency updates and grouping for JavaScript packages are managed through Bun. There are no yarn.lock or package-lock.json files in the repository.
Removal of Mixed Lockfiles#
The project uses a single lockfile for each package ecosystem: Gemfile.lock for Ruby and bun.lockb for JavaScript (managed by Bun). There is no evidence of mixed lockfiles (such as both yarn.lock and package-lock.json) in the repository. This practice prevents dependency resolution conflicts and ensures consistent, reproducible builds across environments. Mixed lockfiles are discouraged because they can cause unpredictable behavior in dependency installation and increase maintenance complexity.
Note: If you previously used yarn.lock or package-lock.json, these files have been removed in favor of bun.lockb. All JavaScript dependencies should be managed exclusively with Bun.
Guidance for Maintaining and Updating CI/CD Workflows#
- Keep GitHub Actions and Docker action versions up to date to benefit from security patches and new features.
- Regularly review and adjust Dependabot settings, including update schedules, grouping, and ignored versions, to match project needs and minimize maintenance overhead.
- Use dependency grouping to reduce noise from individual update PRs and to batch related changes for easier review and testing.
- Ignore major dependency updates that are likely to introduce breaking changes, and plan for these upgrades as dedicated tasks with appropriate testing.
- Maintain a single lockfile per package ecosystem (
Gemfile.lockfor Ruby,bun.lockbfor JavaScript/Bun) to avoid dependency conflicts and ensure reliable builds. - Use mise to manage and pin all development tool versions (Ruby, Bun, Just, etc.) for consistency across local and CI environments.
- Periodically audit workflow steps and secrets (such as
CC_TEST_REPORTER_IDand Docker registry tokens) to ensure they are current and securely managed. - Monitor workflow run times and logs to identify bottlenecks or failures, and optimize steps as needed for efficiency and reliability.
These practices help maintain a robust, secure, and maintainable CI/CD pipeline that supports efficient development and reliable deployments.