Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Run on LocalStack

on:
push:
paths-ignore:
- '**.md'
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:

permissions:
contents: read

jobs:
pipeline:
name: ${{ matrix.sample }}
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
sample:
- 1-codebuild-compile-s3-upload
- 2-codebuild-test-codeartifact-publish
defaults:
run:
working-directory: ${{ matrix.sample }}
steps:
- name: Checkout
uses: actions/checkout@v4

# LocalStack stops tracking a build whose image is still downloading,
# so pull the CodeBuild images (about 17 GB) before starting the pipeline
- name: Pull the CodeBuild images
run: |
# Anonymous ECR Public pulls are rate limited per IP, which runners share
for image in public.ecr.aws/codebuild/amazonlinux-x86_64-standard:5.0 localstack/aws-codebuild-local:2; do
for attempt in 1 2 3 4 5; do
docker pull -q "$image" && break
[ "$attempt" = 5 ] && exit 1
echo "Pull of $image failed, retrying in 60s"
sleep 60
done
done

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22

- name: Install lstk
run: |
npm install -g @localstack/lstk
lstk setup aws --force --non-interactive

- name: Start LocalStack
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
# Forwarded as CODEPIPELINE_GH_TOKEN, used to download the source archives from GitHub
LOCALSTACK_CODEPIPELINE_GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: lstk start

- name: Run the pipeline
env:
MAX_WAIT_SECONDS: 1200
run: bash run.sh

- name: Show pipeline state and LocalStack logs
if: failure()
run: |
lstk aws codepipeline get-pipeline-state --name demo-pipeline || true
lstk aws codepipeline list-action-executions --pipeline-name demo-pipeline || true
builds=$(lstk aws codebuild list-builds --query 'ids' --output text || true)
[ -n "$builds" ] && lstk aws codebuild batch-get-builds --ids $builds \
--query 'builds[].{id: id, status: buildStatus, phases: phases[].[phaseType, phaseStatus, contexts[0].message]}' || true
docker ps -a
docker images
df -h /
lstk logs | grep -vE 'ListPipelineExecutions|ListActionExecutions' | tail -400
18 changes: 15 additions & 3 deletions 1-codebuild-compile-s3-upload/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,22 @@ lstk aws codepipeline create-pipeline --pipeline file://./pipeline.json
lstk aws codepipeline list-pipeline-executions --pipeline-name demo-pipeline

# Wait for pipeline to finish
MAX_WAIT_SECONDS=${MAX_WAIT_SECONDS:-1800}
status=
until [[ $status =~ Succeeded ]]; do
status=$(lstk aws codepipeline list-pipeline-executions --pipeline-name demo-pipeline --output text --query pipelineExecutionSummaries[0].status)
waited=0
until [[ $status == Succeeded ]]; do
if [[ $status =~ ^(Failed|Stopped|Superseded)$ ]]; then
echo "Pipeline execution ended with status $status"
lstk aws codepipeline get-pipeline-state --name demo-pipeline
exit 1
fi
if (( waited >= MAX_WAIT_SECONDS )); then
echo "Pipeline did not finish within ${MAX_WAIT_SECONDS}s, last status: $status"
exit 1
fi
sleep 5
waited=$((waited + 5))
status=$(lstk aws codepipeline list-pipeline-executions --pipeline-name demo-pipeline --output text --query 'pipelineExecutionSummaries[0].status')
done

# Retrieve build
Expand All @@ -42,4 +54,4 @@ lstk aws s3 cp s3://output-bucket/fzf/fzf .
# Try build
file fzf
chmod +x fzf
./fzf --version
./fzf --version | grep '^0.62 '
21 changes: 18 additions & 3 deletions 2-codebuild-test-codeartifact-publish/run.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/env bash
#!/usr/bin/env bash

set -xeuo pipefail

Expand Down Expand Up @@ -40,10 +40,22 @@ lstk aws s3 mb s3://demo-artif-bucket
lstk aws codepipeline create-pipeline --pipeline file://./demo-pipeline.json

# Wait for the pipeline to finish
MAX_WAIT_SECONDS=${MAX_WAIT_SECONDS:-1800}
status=
until [[ $status =~ Succeeded ]]; do
status=$(lstk aws codepipeline list-pipeline-executions --pipeline-name demo-pipeline --output text --query pipelineExecutionSummaries[0].status)
waited=0
until [[ $status == Succeeded ]]; do
if [[ $status =~ ^(Failed|Stopped|Superseded)$ ]]; then
echo "Pipeline execution ended with status $status"
lstk aws codepipeline get-pipeline-state --name demo-pipeline
exit 1
fi
if (( waited >= MAX_WAIT_SECONDS )); then
echo "Pipeline did not finish within ${MAX_WAIT_SECONDS}s, last status: $status"
exit 1
fi
sleep 5
waited=$((waited + 5))
status=$(lstk aws codepipeline list-pipeline-executions --pipeline-name demo-pipeline --output text --query 'pipelineExecutionSummaries[0].status')
done

# Configure NPM to work with the local CodeArtifact repository
Expand All @@ -52,3 +64,6 @@ lstk aws codeartifact login --tool npm --domain demo-domain --repository demo-re

# Try to download the NPM package
npm pack my-lodash-fork

# Check the downloaded package is the fork published by the pipeline
tar -xzOf my-lodash-fork-*.tgz package/package.json | grep '"name": "my-lodash-fork"'
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ export LOCALSTACK_AUTH_TOKEN=<your-auth-token>
export CODEPIPELINE_GH_TOKEN=<your-github-pat>
```

If you start LocalStack with `lstk start`, export the token as `LOCALSTACK_CODEPIPELINE_GH_TOKEN` instead. `lstk` only forwards `LOCALSTACK_`-prefixed variables to the container, which strips the prefix.

Each `run.sh` fails if the pipeline execution fails or takes longer than `MAX_WAIT_SECONDS` (default 1800).

Pull the CodeBuild images before the first run:

```bash
docker pull public.ecr.aws/codebuild/amazonlinux-x86_64-standard:5.0
docker pull localstack/aws-codebuild-local:2
```

LocalStack stops tracking a build if its image is still downloading a few seconds after the build starts, and the pipeline then stays `InProgress`.

## Samples

- [1-codebuild-compile-s3-upload](1-codebuild-compile-s3-upload/README.md): Builds `fzf` with CodeBuild and uploads the resulting binary to S3 through CodePipeline.
Expand Down
Loading