amazon-web-servicesamazon-elastic-beanstalkaws-codepipelineaws-codebuildbuildspec

How can I fetch a commit message in AWS CodePipeline/CodeBuild to implement a `[skip ci]` command?


I'm using an AWS CodePipeline with GitHub Connections as the source action to deploy a Python app to an AWS Elastic BeanStalk. I’d like to emulate GitHub Actions' [skip ci] feature by detecting a commit message prefix and exiting early if present, canceling the build stage.

I found this post, but the commented solution doesn't work with GitHub connections as the source of the action.

I added the following to my buildspec.yml:

version: 0.2

env:
  git-credential-helper: yes

phases:
  install:
    runtime-versions:
      python: 3.12
    commands:
      - COMMIT_MESSAGE=$(git log -1 --pretty=%B)
      - if [[ "$COMMIT_MESSAGE" == *"[skip ci]"* ]]; then echo "Skipping build"; exit 0; fi

But the build fails almost immediately with:

fatal: not a git repository (or any parent up to mount point /codebuild)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

[Container] 2025/04/09 18:15:33.812706 Command did not exit successfully COMMIT_MESSAGE=$(git log -1 --pretty=%B) exit status 128
[Container] 2025/04/09 18:15:33.846916 Phase complete: INSTALL State: FAILED
[Container] 2025/04/09 18:15:33.846931 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: COMMIT_MESSAGE=$(git log -1 --pretty=%B). Reason: exit status 128

It looks like the CodeBuild environment directory isn’t recognized as a Git repository, so git command don't work.

Is there a built‑in way for CodePipeline/CodeBuild to expose the commit message as an environment variable or parameter? If direct access isn’t possible, what workaround would you recommend (e.g., using a Lambda pre‑build step, custom webhook, or other mechanism)?

Any example snippets of a working buildspec.yml or pipeline configuration would be greatly appreciated.

Thank you for your time!


Solution

  • I've figured out how to do it. Here were the steps for me, considering my CodePipeline consists of Source (CodeConnections) -> Build (CodeBuild) -> Deploy (Elastic Beanstalk):

    1. Set the variable namespace in the source stage. I chose SourceVariables.
    2. Create the COMMIT_MSG environment variable in the build stage as #{SourceVariables.CommitMessage} with the Plaintext type.
    3. Create the PIPELINE_NAME environment variable in the build stage with the hardcoded value of your pipeline name and the Plaintext type.
    4. Create the PIPELINE_EXECUTION_ID environment variable in the build stage as #{codepipeline.PipelineExecutionId} with the Plaintext type.
    5. Grant the codepipeline:StopPipelineExecution permission to the CodeBuild service role on your CodePipeline resource.
    6. Add some form of the below exerpt to your buildspec:
    phases:
      build:
        commands:
          - |
            if [[ "$COMMIT_MSG" == *"[skip ci]"* ]]; then
              echo "Skipping EBS deploy"
              aws codepipeline stop-pipeline-execution \
                --pipeline-name "$PIPELINE_NAME" \
                --pipeline-execution-id "$PIPELINE_EXECUTION_ID" \
                --reason "Skip CI commit prefix"
              exit 0
            fi