Skip to main content
In the previous lesson we created a simple CI/CD pipeline connected to GitHub and implemented a basic deploy phase. This article digs into the CodeBuild buildspec YAML used in that pipeline and shows a complete, production-ready example. You’ll learn:
  • The full buildspec structure and common patterns
  • Environment variables from inline definitions, Systems Manager Parameter Store, and Secrets Manager
  • How to publish primary and secondary artifacts
  • Integrating test reports (report groups)
  • Effective caching strategies to reduce build time
We’ll use the sample pipeline from the earlier demo (moving the sample app from v0.6.0 → v1.0.0) and inspect the CodeBuild project as our starting point.
A screenshot of the AWS CodeBuild console showing the project "devops-020-100-build." The page displays configuration details (GitHub source, primary repository, artifacts location, service role) and a Build history panel.
Complete example buildspec.yml (overview) Read the example first for an overview. The sections after break down the key elements in detail.
Repository root and buildspec location Place the buildspec.yml at the repository root so CodeBuild automatically discovers it when configured to use the source root. The sample repository used in this demo stores the buildspec at the top-level.
A GitHub repository page in dark mode for a project named "020-100-sample-app," showing a file list (src, tests, .gitignore, README.md, etc.). The README header "Sample Application for Demo 020-100" and the repository sidebar (About, Releases, Contributors) are also visible.
Buildspec anatomy — top-level keys Use version: 0.2 to access reports, cache, exported variables, and improved phase semantics. The primary top-level keys you’ll see and use are: Environment (env) keys explained Phases and execution order CodeBuild runs phases in this exact order: install → pre_build → build → post_build. A condensed view of common phase responsibilities: Important: install.finally always runs regardless of earlier failures (similar to try/finally). Use on-failure when you want a phase to continue even if one of its commands fails.
Set on-failure: CONTINUE when you want later phases to execute even if the current phase returns a non-zero exit code. The default ABORT stops the build when a phase fails. Check the AWS CodeBuild docs for current retry and failure behaviors: https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html
Environment variable sources in practice
  • Inline variables (fast, visible in console): defined under env.variables. Example: BUILD_ENVIRONMENT: "demo".
  • Systems Manager Parameter Store: defined under env.parameter-store, pass parameter names or paths. Ensure the CodeBuild service role has ssm:GetParameters.
  • Secrets Manager: defined under env.secrets-manager. You can reference secret-id or secret-id:key to extract a field from a JSON secret. Ensure the CodeBuild role has Secrets Manager read/decrypt permissions.
Tip: Grant minimal IAM permissions to the CodeBuild service role: ssm:GetParameters for Parameter Store entries and secretsmanager:GetSecretValue for Secrets Manager entries. Missing permissions will cause environment variable decryption to fail at the start of the build.
Built-in CodeBuild environment variables CodeBuild injects several built-in variables with the CODEBUILD_ prefix. Commonly used ones include:
  • CODEBUILD_BUILD_NUMBER — incremental build number
  • CODEBUILD_RESOLVED_SOURCE_VERSION — commit SHA or source version
  • CODEBUILD_BUILD_SUCCEEDING — 1 when the build is successful
Use env.exported-variables to make any of these available to downstream pipeline actions. Inspecting env resolution in logs When the build starts, CodeBuild logs environment resolution and decryption. Example log excerpt:
You can also view resolved environment variables for an individual run from the CodeBuild console.
Screenshot of the AWS CodeBuild console showing a build project’s details and the Environment variables tab. The page lists variables like BUILD_ENVIRONMENT, NOTIFICATION_TOPIC, and DOCKER_USERNAME with the left-hand navigation menu visible.
Running tests and integrating reports Best practice is to write JUnit-style and coverage reports into a reports/ directory and configure the reports block in buildspec. CodeBuild captures these and surfaces them under Report groups in the console.
  • pytest example flags used in the buildspec:
    • --junitxml=reports/test-results.xml (JUnit-style test report)
    • --cov-report=xml:reports/coverage.xml (coverage XML)
  • Configure reports in buildspec with base-directory and file-format, for example JUNITXML or COBERTURAXML.
Artifacts — primary and secondary Primary artifacts typically contain the packaged application (Wheels, tarballs, Docker context, etc.). Secondary artifacts are useful for storing test reports or other separate outputs. Key artifact options:
  • files: Glob patterns that specify which files to bundle into the artifact (e.g., dist/**/*).
  • base-directory: Folder that acts as the root for artifacts.
  • discard-paths: no preserves directory structure inside the artifact; yes flattens it.
  • name: Artifact name supports variable interpolation, e.g., "myapp-${CODEBUILD_BUILD_NUMBER}".
  • secondary-artifacts: Define additional named artifacts (e.g., test reports).
Artifact configuration and console views are shown here:
A screenshot of the AWS CodeBuild console showing a build project's Artifacts and Cache configuration, including S3 artifact upload locations, artifact identifiers (like "test-reports"), and encryption settings. The left sidebar displays CodeBuild navigation items such as Build project, Build history, and Report groups.
Build caching strategies Caching dependency directories dramatically reduces build time for repeated runs. CodeBuild supports local caching via the cache.paths block inside the buildspec and S3-based caching configured on the project. Typical cache entries:
  • Python pip cache: /root/.cache/pip/**/*
  • Node dependencies: node_modules/**/*
In this demo, caching these paths reduced repeat build time from ~90s to ~35s. Viewing a build run and results After a build completes you can inspect:
  • Full build logs (console or download)
  • Report groups (test and coverage reports in the console)
  • Exported environment variables accessible to downstream pipeline actions
  • Artifacts stored in S3 (downloadable bundles or expanded files)
Example of environment and compute configuration as displayed in the CodeBuild console:
A screenshot of the AWS CodeBuild console on the "Environment variables" tab showing a list of environment variables (e.g., BUILD_ENVIRONMENT = demo, NOTIFICATION_TOPIC, DOCKER_USERNAME) and their types. The left sidebar shows Developer Tools > CodeBuild navigation items.
A screenshot of the AWS CodeBuild console displaying a build project's Environment and Artifacts settings, showing the build image, compute type (EC2), compute resources (2 vCPUs, 4 GiB), service role ARN, and timeouts. The left sidebar shows the Developer Tools navigation for CodeBuild.
Summary checklist
  • Use version: 0.2 to leverage reports, cache, exported-variables, and improved phases.
  • Choose env sources appropriately: inline variables, SSM Parameter Store, and Secrets Manager. Ensure the CodeBuild role has ssm:GetParameters and secretsmanager:GetSecretValue as needed.
  • Keep phase structure: install → pre_build → build → post_build. Use install.finally for guaranteed cleanup and on-failure to control continuation.
  • Integrate test reporting using reports with JUNITXML and coverage formats; store outputs under a reports/ base-directory.
  • Configure primary and secondary artifacts intentionally and use discard-paths according to how you want the archive structured.
  • Enable caching for dependency directories to speed up iterative builds — consider S3 caching for longer-lived caches.
Next steps If you want, I can:
  • extract a minimal buildspec tailored for a single runtime (e.g., Node.js-only),
  • convert this buildspec for Docker image builds,
  • or produce a variant that uses S3 caching instead of local container caching.
Which variant would you like to see?

Watch Video

Practice Lab