CI Pipeline
CI pipeline: typecheck + lint + build
CI Pipeline
The ci.yml workflow defines the Continuous Integration (CI) pipeline for the Odys project, residing in the .github/workflows/ci.yml file. This pipeline is a critical component of the development process, designed to automatically verify the quality and buildability of the codebase whenever changes are introduced. By running a series of automated checks, it helps maintain code health, catch errors early, and ensure that the application remains in a deployable state.
Overview
This GitHub Actions workflow is configured to trigger automatically on two primary events:
- Every
pushto themainbranch, ensuring that all merged changes are validated. - Every
pull_requesttargeting themainbranch, providing immediate feedback on proposed changes before they are integrated.
The workflow is structured into two distinct jobs: check and build. This separation of concerns allows for a clear progression of validation steps. The build job is explicitly configured to needs: check, meaning it will only execute if the check job completes successfully. This dependency ensures that no code is built unless it first passes all static analysis and tests, saving computational resources and providing a more reliable build artifact.
The check Job: Typecheck, Lint & Tests
The check job, aptly named "Typecheck, Lint & Tests", is the first line of defense for code quality. It runs on an ubuntu-latest environment, providing a consistent execution context.
The steps within this job are:
- Checkout Code: The
actions/checkout@v6action fetches the repository's code, making it available for subsequent steps. - Setup Node.js: The
actions/setup-node@v6action configures the environment with Node.js version 20. It also utilizesnpmcaching, which significantly speeds up subsequent workflow runs by reusing downloaded dependencies. - Install Dependencies: The
npm cicommand installs project dependencies. Usingnpm ci(clean install) instead ofnpm installis a deliberate choice for CI environments, as it guarantees that the exact versions specified inpackage-lock.jsonare installed, leading to more reproducible builds. - Typecheck: This step executes
npx tsc --noEmit. The TypeScript compiler (tsc) is run to perform static type analysis across the entire codebase. The--noEmitflag is crucial here; it instructs TypeScript to only check for type errors without generating any JavaScript output files. This makes the step faster and ensures it focuses solely on type correctness. - Lint: The
npm run lintcommand invokes the project's linter. This step enforces coding standards, identifies stylistic issues, and catches potential programming errors, contributing to a more consistent and maintainable codebase. - Unit tests: Finally,
npm testruns the project's suite of unit tests. This step verifies the correctness of individual components and functions, ensuring that recent changes have not introduced regressions.
The build Job: Application Compilation
The build job, named "Build", is responsible for compiling the application into a deployable artifact. It also runs on ubuntu-latest and, as mentioned, needs the check job to pass before it begins.
A key aspect of the build job is the extensive list of environment variables it requires. These variables, sourced from GitHub Secrets, are essential for the build process to correctly configure the application for various services and integrations. They include:
NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_ANON_KEYfor Supabase integration.SUPABASE_SERVICE_ROLE_KEYandDATABASE_URLfor database access.STRIPE_SECRET_KEY,STRIPE_BASIC_PRICE_ID,STRIPE_WEBHOOK_SECRET, andNEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYfor Stripe payment processing, including theSTRIPE_BASIC_PRICE_IDwhich corresponds to the basic plan's pricing.EVOLUTION_API_URL,EVOLUTION_API_KEY, andEVOLUTION_INSTANCEfor the Evolution API, likely related to WhatsApp integration given the project's use of 19 WhatsApp message templates.CRON_SECRETfor securing cron job endpoints like/api/cron/remindersand/api/cron/whatsapp-watchdog.RESEND_API_KEYfor email services.UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKENfor Upstash Redis, which is used for rate limiting across 6 different categories, includingbookingandaichat.SENTRY_AUTH_TOKENfor error monitoring.
The steps within the build job are similar to the initial setup of the check job:
- Checkout Code:
actions/checkout@v6retrieves the source code. - Setup Node.js:
actions/setup-node@v6configures Node.js version 20 andnpmcaching. - Install Dependencies:
npm ciinstalls dependencies reproducibly. - Build: The
npm run buildcommand executes the project's build script. This typically involves transpiling code, optimizing assets, and generating the final output files ready for deployment.
Design Decisions
The structure of this CI pipeline reflects several intentional design choices aimed at efficiency, reliability, and maintainability:
- Sequential Job Execution (
needs: check): By making thebuildjob dependent on thecheckjob, the pipeline ensures that resources are not wasted on building code that already contains errors. This "fail fast" approach provides quicker feedback to developers and reduces overall CI costs. - Dedicated
checkJob for Fast Feedback: Separating typechecking, linting, and testing into a distinctcheckjob allows for rapid validation of code quality. Developers receive quick feedback on common issues without waiting for a full application build, which is often a more time-consuming process. npm cifor Reproducibility: The use ofnpm ciinstead ofnpm installis a standard practice in CI environments. It guarantees that the exact dependency tree defined inpackage-lock.jsonis used, preventing unexpected build failures due to new or updated package versions.tsc --noEmitfor Type Safety: Running TypeScript with--noEmitin thecheckjob ensures that type correctness is verified without the overhead of generating JavaScript files. This keeps thecheckjob focused and efficient.- Comprehensive Environment Variables for
build: Providing a complete set of environment variables to thebuildjob ensures that the application is compiled with all necessary configurations for its various integrations, such as Supabase, Stripe, and WhatsApp. This prevents issues that might arise from missing configuration during the build phase.
Potential Improvements
While the current CI pipeline provides a solid foundation for code quality and build verification, several opportunities exist to enhance its efficiency and coverage:
- Parallelize Independent Checks: The
Typecheck,Lint, andUnit testssteps within thecheckjob currently execute sequentially. Since these steps are largely independent of each other, they could be configured to run in parallel. This would involve restructuring thecheckjob to leverage GitHub Actions' ability to run steps concurrently, significantly reducing the overall execution time of thecheckphase. - Integrate Drizzle Schema Validation: The project uses Drizzle ORM, managing 10 tables including
professionals,appointments, andclients. Adding a step to validate the Drizzle schema against the database or generated types (e.g., using adrizzle-kit checkcommand if available) within thecheckjob could catch schema drift or definition errors early. This would prevent potential runtime issues related to database schema mismatches before deployment. - Run
npm auditfor Dependency Security: The project relies on 35 direct dependencies and 11 development dependencies. Incorporating annpm auditstep into thecheckjob would automatically scan for known security vulnerabilities in the dependency tree. This provides an additional layer of security assurance, identifying potential risks in third-party packages before the code is built or deployed.
References
.github/workflows/ci.yml