DVA-C02Chapter 98 of 101Objective 3.3

CodeBuild buildspec.yml Reference

This chapter provides a comprehensive reference for the AWS CodeBuild buildspec.yml file, the declarative build specification that defines every step of a CodeBuild project. For the DVA-C02 exam, understanding buildspec syntax, phases, environment variables, artifacts, and caching is critical, as approximately 10-15% of questions touch on CodeBuild or integrate it with other services like CodePipeline. Mastery of buildspec.yml ensures you can configure builds correctly, troubleshoot failures, and optimize build performance—skills directly tested in the Deployment domain (Objective 3.3).

25 min read
Intermediate
Updated May 31, 2026

CodeBuild buildspec.yml as a Recipe Card

Think of a buildspec.yml file as a recipe card for a master chef (AWS CodeBuild). The recipe lists ingredients (source code, environment variables), tools (runtime versions, build commands), and steps (pre-build, build, post-build) in a specific order. Just as a recipe must be precise—specifying oven temperature (e.g., 350°F) and baking time (e.g., 30 minutes)—the buildspec.yml must specify exact commands, environment settings, and artifacts. If the recipe says 'bake until golden,' the chef must interpret; similarly, vague commands in buildspec.yml cause failures. The chef cannot skip steps or rearrange them; CodeBuild executes phases sequentially (install, pre_build, build, post_build). The recipe also includes optional notes (e.g., 'add chocolate chips if desired'), analogous to optional 'finally' and 'reports' sections. The final dish is the artifact, like a packaged application. A good recipe ensures consistency every time, just as a well-written buildspec.yml ensures reproducible builds across runs.

How It Actually Works

What is buildspec.yml and Why It Exists

The buildspec.yml file is a YAML-formatted configuration file that tells AWS CodeBuild exactly what to do during a build. It is the heart of a CodeBuild project, defining the sequence of phases (install, pre_build, build, post_build), environment variables, artifacts to produce, cache settings, and reports. Without a buildspec.yml, CodeBuild would have no instructions; you can either include it in your source code (at the root) or define it inline in the CodeBuild console/CLI. The exam tests your ability to write and interpret buildspec.yml correctly, including mandatory vs. optional fields and common pitfalls.

How It Works Internally – Step Through the Mechanism

When a build starts, CodeBuild reads the buildspec.yml and executes phases in this order: 1. Install: Install dependencies (e.g., packages, runtime versions). 2. Pre_build: Commands to run before the main build (e.g., signing in, pulling dependencies). 3. Build: The actual build commands (e.g., compile, test). 4. Post_build: Commands after build (e.g., packaging, notifications). 5. Finally (optional): Always runs, even if previous phases fail.

Each phase can contain multiple commands, and the phase fails if any command returns a non-zero exit code (unless you use || true or similar). The environment is isolated per build; each build runs in a fresh container. CodeBuild also supports batch builds, where multiple builds run in parallel using a batch buildspec.

Key Components, Values, Defaults, and Timers

- version: Required. Must be 0.2 (the current version). Older version 0.1 is deprecated. - run-as: Optional. Linux user to run commands (default: root). Useful for restricted permissions. - env: Optional. Defines environment variables. - variables: Plain text key-value pairs. - parameter-store: References AWS Systems Manager Parameter Store parameters. - secrets-manager: References AWS Secrets Manager secrets. - exported-variables: List of variables to export to subsequent phases (e.g., for batch builds). - phases: Required. Contains install, pre_build, build, post_build, and optionally finally. - Each phase has: - runtime-versions: Map of runtime names to versions (e.g., nodejs: 14). Supported runtimes: Android, Docker, Dotnet, Go, Java, Node.js, PHP, Python, Ruby, etc. Must be specified in install phase. - commands: List of shell commands to execute sequentially. - finally: A list of commands that run after the phase's main commands, regardless of success/failure. Only at the phase level. - artifacts: Required. Defines output files. - files: List of file patterns to include (e.g., **/*). - name: Name of the artifact (default: project name). - discard-paths: Boolean; if true, flattens directory structure. - base-directory: Base directory for relative paths. - secondary-artifacts: Map of additional artifact sets. - cache: Optional. Speeds up builds by caching dependencies. - paths: List of paths to cache (e.g., /root/.npm). - type: Only local is supported (stores in S3 or local). - reports: Optional. Defines test reports. - Report group name with: - files: List of report file patterns. - base-directory: Base directory for report files. - file-format: CUCUMBERJSON or JUNITXML. - batch: Optional. For batch builds. - fast-fail: Boolean; if true, fails entire batch if one build fails. - build-list: List of build-specific overrides. - build-graph: For dependency-based builds.

Timers: CodeBuild has a default build timeout of 60 minutes, configurable up to 8 hours (480 minutes) for on-demand builds, or up to 2 hours for Lambda compute. If no output is produced for 30 minutes (default idle timeout), the build is terminated. These are set in the CodeBuild project, not in buildspec.yml.

Configuration and Verification Commands

Sample buildspec.yml:

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 14
    commands:
      - npm install
  pre_build:
    commands:
      - echo "Running pre-build commands"
  build:
    commands:
      - npm run build
  post_build:
    commands:
      - echo "Build completed on `date`"
artifacts:
  files:
    - '**/*'
  base-directory: 'build'

To validate syntax, you can use aws codebuild batch-get-builds or run a build and check logs. There is no official linter; errors appear in build logs.

How It Interacts with Related Technologies

CodePipeline: buildspec.yml defines the build action in a pipeline stage. CodePipeline triggers CodeBuild with source artifacts and passes output artifacts to next stages.

S3: Artifacts are stored in an S3 bucket (default or custom). Cache can also use S3.

IAM: CodeBuild needs permissions to read source, write artifacts, access Parameter Store/Secrets Manager, and publish logs to CloudWatch Logs.

CloudWatch Logs: Build logs are streamed to CloudWatch Logs by default.

AWS KMS: Artifacts and cache can be encrypted with a KMS key.

GitHub, Bitbucket, S3, CodeCommit: Supported source repositories. The buildspec.yml can be in the source or defined in the project.

Walk-Through

1

Define buildspec.yml in source

Place a valid buildspec.yml file at the root of your source code repository. CodeBuild automatically looks for this file when a build starts. If not found, the build fails unless you provide an inline buildspec in the CodeBuild project configuration. The file must be YAML-formatted and start with `version: 0.2`. Ensure there are no syntax errors (e.g., incorrect indentation) as CodeBuild will report a YAML parse error in the build logs.

2

CodeBuild reads buildspec.yml

When a build is triggered (manually, via CodePipeline, or a webhook), CodeBuild spins up a build environment (container) based on the specified compute type and image. It then reads the buildspec.yml from the source or inline definition. The environment variables, runtime versions, and phases are parsed. If any required field is missing or invalid, the build fails immediately with an error message in the logs.

3

Execute install phase

CodeBuild executes the `install` phase first. It installs any specified runtime versions (e.g., Python 3.8) using the environment's package manager. Then it runs the commands listed under `install` sequentially. If a command fails (non-zero exit), the phase fails and the build stops, unless the `finally` block is present. Common commands include `apt-get update`, `pip install`, or `npm install`. The runtime-versions block is only valid in this phase.

4

Execute pre_build phase

After install, the `pre_build` phase runs. This is where you typically perform pre-build steps like signing in to a registry, pulling dependencies, or running database migrations. Commands run in the same working directory as the source code. If this phase fails, the build stops. Use `finally` to run cleanup commands regardless of success.

5

Execute build phase

The `build` phase contains the main build commands, such as compiling code, running unit tests, or packaging the application. This is the core of the build process. If any command fails, the build stops and is marked as FAILED. The working directory is the root of the source code (or the base-directory if specified). Environment variables defined in the `env` section are available.

6

Execute post_build phase

The `post_build` phase runs after the build phase, regardless of success or failure. Use it for cleanup, sending notifications, or packaging artifacts. If the build phase failed, post_build still runs. However, if post_build itself fails, the build is marked as FAILED. To ensure certain commands always run even if post_build fails, use a `finally` block within the post_build phase.

7

Package and upload artifacts

After all phases complete, CodeBuild collects the files specified in the `artifacts` section. It compresses them into a ZIP file (or multiple ZIPs for secondary artifacts) and uploads them to the configured S3 bucket. If `discard-paths` is true, the directory structure is flattened. The artifact name can be customized; default is the project name. If no artifacts are defined, the build still succeeds but produces no output.

8

Generate reports (if configured)

If the `reports` section is defined, CodeBuild processes test result files (e.g., JUnit XML) and sends them to the CodeBuild console and CloudWatch. Reports can be viewed in the CodeBuild dashboard. The files must match the patterns specified. If report generation fails, the build is not necessarily marked as failed; it depends on the phase that generated the reports.

9

Execute finally block (optional)

The `finally` block, if present at the top level (not inside a phase), runs after all phases complete, regardless of build success or failure. It is used for cleanup actions like removing temporary files or sending final notifications. If the finally block fails, the build is marked as FAILED. Note that finally blocks can also be defined within individual phases to run after that phase's commands.

What This Looks Like on the Job

Enterprise Scenario 1: Continuous Integration for a Microservices Application

A large e-commerce company uses CodeBuild to build and test dozens of microservices. Each service has its own buildspec.yml in its repository. The buildspec.yml specifies runtime-versions for Java 11, installs Maven dependencies, runs unit tests (using JUnit), and produces a JAR artifact. The post_build phase uploads the JAR to an S3 bucket and triggers a deployment via CodeDeploy. To speed up builds, they cache the Maven local repository (~/.m2) using the cache section. This reduces build times from 15 minutes to 3 minutes. They also configure reports to publish test results to CodeBuild, enabling developers to see test failures directly in the console. A common issue is when developers forget to update the buildspec.yml when changing the build tool (e.g., Gradle to Maven), causing the install phase to fail because Maven is not installed.

Enterprise Scenario 2: Multi-Environment Builds with Batch Builds

A SaaS company uses batch builds to build their application for multiple environments (development, staging, production) in parallel. They define a batch buildspec.yml that includes a batch section with a build-list that overrides environment variables for each build (e.g., ENVIRONMENT: dev, ENVIRONMENT: prod). Each build runs the same phases but with different variable values. The artifacts are named differently (e.g., app-dev.zip, app-prod.zip). This approach reduces total build time from 30 minutes (sequential) to 10 minutes (parallel). They must ensure that the build environment is consistent across batches, so they pin runtime versions and use a custom Docker image. A pitfall is using exported-variables incorrectly; if a variable is exported in one batch build, it is not available in another unless explicitly passed.

Enterprise Scenario 3: Compliance-Driven Builds with Auditing

A financial services firm requires that all builds be immutable and auditable. They store buildspec.yml files in CodeCommit and enforce that every build uses a buildspec.yml from the source (not inline). They configure CodeBuild to log all commands to CloudWatch Logs with a retention policy of 7 years. The buildspec.yml includes a finally block that sends a notification to an SNS topic with the build result. They also use Parameter Store to inject database credentials and API keys, avoiding hardcoded secrets. A common misconfiguration is setting env with parameter-store but not granting the CodeBuild service role permission to read the parameter, causing the build to fail with an access denied error.

How DVA-C02 Actually Tests This

What DVA-C02 Tests on buildspec.yml (Objective 3.3)

The exam tests your ability to read, write, and troubleshoot buildspec.yml files. You must know:

The required version field (0.2).

The correct phase order: install, pre_build, build, post_build, finally.

Where runtime-versions are specified (only in install phase).

How to define environment variables, including from Parameter Store and Secrets Manager.

Artifact configuration: files, base-directory, discard-paths, name.

Cache configuration: only local type is supported.

Reports configuration: file-format options (CUCUMBERJSON, JUNITXML).

The difference between phase-level finally and top-level finally.

Batch builds: fast-fail, build-list, build-graph.

Common Wrong Answers and Why Candidates Choose Them

1.

Choosing `version: 0.1`: Candidates think older version is acceptable. But 0.1 is deprecated and not supported in current CodeBuild. The exam expects 0.2.

2.

Putting runtime-versions in pre_build or build phase: Candidates confuse where to specify runtimes. Only valid in install phase.

3.

Thinking cache type can be S3: The cache type is only local; CodeBuild automatically manages local caching. Some candidates think you can specify S3 as type, but that is not supported.

4.

Assuming artifacts are optional: While you can omit artifacts, the exam expects you to know that if you want output, you must define artifacts. Many questions ask about missing artifacts.

5.

Confusing `finally` block placement: Candidates think finally can only be at top level. It can also be inside a phase to run after that phase's commands.

Specific Numbers, Values, and Terms on the Exam

version: 0.2 (mandatory)

Runtime versions: nodejs: 14, python: 3.8, java: corretto11, dotnet: 3.1, go: 1.14, etc.

Environment variable sources: variables, parameter-store, secrets-manager.

Artifact discard-paths: boolean (true/false).

Report formats: CUCUMBERJSON and JUNITXML.

Cache type: local (only option).

Batch fast-fail: boolean.

Edge Cases and Exceptions

If you specify both parameter-store and secrets-manager for the same variable name, the build fails due to duplicate.

If the buildspec.yml is not in the source root and you don't specify an inline buildspec, the build fails.

The finally block at top level runs even if a phase fails, but if the finally itself fails, the build is marked FAILED.

In batch builds, exported-variables are only available within the same build, not across batch builds.

If you use run-as with a non-root user, ensure that user has necessary permissions to execute commands and access files.

How to Eliminate Wrong Answers Using the Underlying Mechanism

If a question asks where to install a runtime, eliminate any phase that is not install.

If a question involves caching dependencies, look for cache with paths and type: local.

If a question asks about securing secrets, the correct answer will use parameter-store or secrets-manager, not plaintext variables.

If a question involves test reports, look for reports with file-format matching the test framework.

If a question involves parallel builds, look for batch with build-list or build-graph.

Key Takeaways

buildspec.yml must start with `version: 0.2`; version 0.1 is deprecated.

Phases execute in order: install, pre_build, build, post_build, finally (if present).

Runtime versions can only be specified in the install phase under `runtime-versions`.

Environment variables can come from plaintext `variables`, `parameter-store`, or `secrets-manager`.

Artifacts are always packaged as ZIP; use `files`, `base-directory`, `discard-paths`, and `name`.

Cache type is only `local`; you cannot specify S3 as cache type.

Reports support `CUCUMBERJSON` and `JUNITXML` file formats.

The `finally` block runs after all phases, even if a phase fails.

Batch builds use `batch` section with `fast-fail`, `build-list`, or `build-graph`.

If buildspec.yml is missing and no inline is provided, the build fails.

Use `run-as` to specify a Linux user for running commands (default root).

Exported variables (`exported-variables`) are only available within the same build, not across batch builds.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

buildspec.yml in source code

Stored in version control, ensuring traceability.

Automatically used when source is fetched.

Can be different per branch if placed in branch-specific paths.

Must be present in every source commit; otherwise build fails.

Preferred for production pipelines to enforce consistency.

Inline buildspec in CodeBuild project

Defined directly in CodeBuild project settings (console/CLI).

Overrides any buildspec.yml in source if both exist.

Useful for quick tests or when source cannot contain buildspec.

Not version-controlled; changes are manual.

Risk of drift between project configuration and source.

Watch Out for These

Mistake

The buildspec.yml file must be named exactly 'buildspec.yml' and placed in the root of the source.

Correct

While the default location is the root directory named 'buildspec.yml', you can specify a different location (e.g., 'config/build.yml') in the CodeBuild project configuration. The exam typically tests the default behavior, but be aware of the override option.

Mistake

You can specify multiple runtime versions in the build phase.

Correct

Runtime versions can only be specified in the `install` phase under `runtime-versions`. Attempting to specify them elsewhere results in a build failure.

Mistake

The 'finally' block runs only if the build succeeds.

Correct

The `finally` block runs regardless of build success or failure, both at the top level and within phases. It is intended for cleanup actions that must always execute.

Mistake

Artifacts must be compressed as ZIP; you can choose other formats.

Correct

CodeBuild automatically compresses artifacts into ZIP files. You cannot change the format. The exam expects you to know that artifacts are always ZIP.

Mistake

Caching can be configured to use an S3 bucket directly.

Correct

The cache `type` only supports `local`. CodeBuild manages local caching automatically; you cannot specify an S3 bucket as the cache type. However, the cache is stored in an S3 bucket managed by CodeBuild, but that is not configurable.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

What is the correct version for buildspec.yml in AWS CodeBuild?

The correct version is `0.2`. Version `0.1` is deprecated and no longer supported. Always start your buildspec.yml with `version: 0.2`. The exam expects this exact value.

Can I use environment variables from AWS Systems Manager Parameter Store in buildspec.yml?

Yes, you can reference parameters from SSM Parameter Store using the `parameter-store` key under `env`. For example: `env: parameter-store: DB_URL: /myapp/db_url`. Ensure the CodeBuild service role has permission to read the parameter. Similarly, use `secrets-manager` for secrets stored in AWS Secrets Manager.

What happens if a command in a phase fails?

If any command in a phase returns a non-zero exit code, the phase is considered failed, and the build stops (unless a `finally` block is present). The build status becomes FAILED. To ignore a command failure, you can append `|| true` to the command.

How do I cache dependencies to speed up builds?

Use the `cache` section in buildspec.yml. Specify `paths` to directories you want to cache (e.g., `/root/.npm` for npm packages). The `type` must be `local`. CodeBuild automatically manages the cache and stores it in an S3 bucket. Example: `cache: paths: - '/root/.npm'`.

What is the difference between phase-level finally and top-level finally?

A phase-level `finally` block runs after that phase's commands, regardless of success or failure. The top-level `finally` block runs after all phases complete, regardless of overall build success. Both are optional. If a phase-level finally fails, the phase is marked failed, but the top-level finally still runs.

Can I have multiple artifact sets?

Yes, you can define secondary artifacts using the `secondary-artifacts` map under `artifacts`. Each secondary artifact has its own `files`, `base-directory`, `discard-paths`, and `name`. This is useful when you want to produce separate outputs from a single build.

How do I specify runtime versions like Python 3.8 or Node.js 14?

Runtime versions are specified under `phases.install.runtime-versions`. For example: `phases: install: runtime-versions: python: 3.8`. Supported runtimes include Android, Docker, Dotnet, Go, Java, Node.js, PHP, Python, Ruby. Only specify them in the install phase.

Terms Worth Knowing

Ready to put this to the test?

You've just covered CodeBuild buildspec.yml Reference — now see how well it sticks with free DVA-C02 practice questions. Full explanations included, no account needed.

Done with this chapter?