Skip to content

Make the url-shortener diagram vertical with white subgraph backgrounds #316

Make the url-shortener diagram vertical with white subgraph backgrounds

Make the url-shortener diagram vertical with white subgraph backgrounds #316

Workflow file for this run

name: Samples CI
# Tests Azure samples against the LocalStack emulator.
# Each test runs in its own job. Set DEFAULT_RUN_MODE to 'changed' to only run affected tests.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
pull_request:
branches: [ main ]
workflow_dispatch:
inputs:
run_mode:
description: "Test mode: 'all' runs every test, 'changed' runs only tests with modified files"
required: false
type: choice
options:
- all
- changed
default: changed
arch:
description: "Architecture: 'both' runs every test on each architecture it supports"
required: false
type: choice
options:
- both
- amd64
- arm64
default: both
# Defaults for pull_request events (change DEFAULT_RUN_MODE to 'changed' to only run affected tests)
env:
DEFAULT_RUN_MODE: changed
DEFAULT_ARCH: both
# Least-privilege default: no permissions unless a job explicitly opts in.
permissions: {}
jobs:
# Lightweight job that builds the dynamic test matrix for the main test jobs
setup:
name: "Build Test Matrix"
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
matrix: ${{ steps.build-matrix.outputs.matrix }}
has_tests: ${{ steps.build-matrix.outputs.has_tests }}
steps:
- name: Checkout repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0 # Full history needed for git diff in "changed" mode
persist-credentials: false
- name: Build dynamic matrix
id: build-matrix
env:
# Untrusted dispatch inputs routed via env, not interpolated into the shell (template-injection)
RUN_MODE_INPUT: ${{ github.event.inputs.run_mode }}
ARCH_INPUT: ${{ github.event.inputs.arch }}
run: |
# Pick run mode and architecture: manual dispatch uses the dropdowns, PRs use the env defaults
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
RUN_MODE="${RUN_MODE_INPUT}"
ARCH="${ARCH_INPUT}"
else
RUN_MODE="${{ env.DEFAULT_RUN_MODE }}"
ARCH="${{ env.DEFAULT_ARCH }}"
fi
# In "changed" mode, determine the base commit to diff against
BASE_SHA=""
if [[ "$RUN_MODE" == "changed" ]]; then
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
else
BASE_SHA=$(git rev-parse origin/main 2>/dev/null || git rev-parse HEAD~1)
fi
fi
.github/scripts/build-matrix.sh "$RUN_MODE" "$BASE_SHA" "$ARCH"
# Each test runs in its own job — one matrix entry per test/architecture from the setup job
scripts:
name: "Test: ${{ matrix.name }}"
needs: setup
if: needs.setup.outputs.has_tests == 'true' # Skip entirely when no tests match
environment: AZURE
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
# ubuntu-22.04 for amd64, ubuntu-22.04-arm for arm64 — the matrix carries the label.
# GitHub-hosted arm64 runners are free for public repositories.
runs-on: ${{ matrix.runner }}
permissions:
contents: read
env:
IMAGE_NAME: localstack/localstack-azure
DEFAULT_TAG: latest
steps:
- name: Checkout repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up environment
env:
RUNNER_TEMP_DIR: ${{ runner.temp }}
run: echo "AZURE_CONFIG_DIR=${RUNNER_TEMP_DIR}/azure-cli" >> "$GITHUB_ENV"
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: '3.12'
cache: 'pip'
- name: Set up .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: '10.0'
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: '25'
- name: Install System Dependencies
# Essential tools for script execution, app packaging, and database connectivity.
# jq: for parsing JSON responses from Azure CLI.
# zip: for packaging function/web apps.
# unixodbc-dev & libsnappy-dev: required for Python database drivers (pyodbc, pymongo).
# default-mysql-client: provides the `mysql` CLI used by the MySQL flexible-server sample
# to create the application user and seed the database schema in the local emulator.
# postgresql-client: provides the `psql` CLI used by the PostgreSQL flexible-server sample
# to create the application role and seed the database schema in the local emulator.
run: |
sudo apt-get update
sudo apt-get install -y jq zip unixodbc-dev libsnappy-dev default-mysql-client postgresql-client
find . -name "*.sh" -exec chmod +x {} +
- name: Install Terraform
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
with:
terraform_version: "1.5.0"
terraform_wrapper: false
- name: Install test dependencies
# Mirroring the localstack-pro approach: install all Python dependencies
# (including the localstack CLI) into a virtual environment to avoid system-level conflicts.
run: make install
- name: Login to Docker Hub
# Mandatory login to Docker Hub to benefit from higher rate limits for authenticated pulls.
# This prevents '429 Too Many Requests' errors during the pull of large emulator images.
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_PULL_USERNAME }}
password: ${{ secrets.DOCKERHUB_PULL_TOKEN }}
- name: Free up disk space
# Azure emulator images are large. Pruning unused Docker objects ensures enough
# disk space is available on the GitHub runner for image pulls and sidecar containers.
run: |
docker system prune -af --volumes
docker builder prune -af
- name: Pull LocalStack Azure Image
# Explicitly pull the image before starting. This mirrors the "Build Docker Image"
# step in localstack-pro and ensures the pull logic is separated from the start logic.
run: docker pull ${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}
- name: Start LocalStack
# Run the emulator in detached mode using the virtual environment.
# The readiness wait is generous because the architecture matrix roughly doubles
# the number of concurrent jobs, and the contention for Docker pulls and runner
# I/O pushed some starts past a 120s budget. A healthy emulator still returns as
# soon as it is ready, so a larger timeout costs nothing on the happy path.
run: |
source .venv/bin/activate
python -m localstack_cli.cli.main start -d
python -m localstack_cli.cli.main wait -t 300
env:
IMAGE_NAME: ${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}
LOCALSTACK_AUTH_TOKEN: ${{ secrets.TEST_LOCALSTACK_AUTH_TOKEN }}
DOCKER_FLAGS: "-e MSSQL_ACCEPT_EULA=Y"
LS_LOG: "DEBUG"
DISABLE_EVENTS: "1"
ACTIVATE_PRO: "1"
DNS_ADDRESS: "0"
- name: Install lstk CLI
# Required by run-samples.sh to proxy Azure CLI calls to the emulator
# via `lstk az` (replaces the deprecated azlocal wrapper).
# https://github.com/localstack/lstk
#
# Pinned, like every action in this workflow: an unpinned install means an upstream
# release lands in every run at once, with no commit to point at when things break.
# Bump deliberately.
env:
# 0.19.0, not the current 0.20.0. Since 0.20.0 was published (2026-07-30 11:10) every
# sample run has failed at `lstk az start-interception` with "LocalStack Azure Emulator
# is not running" - 6 runs across 4 unrelated branches, while the emulator was up and
# answering its health endpoint. Detection fails on roughly 80% of fresh runners, is
# decided before the first call (retries never recover it), and reproduces on neither
# arch locally. Every run on 0.19.0 was green.
# Revert to the latest release once the detection regression is fixed upstream.
LSTK_VERSION: "0.19.0"
run: |
MAX_RETRIES=3
DELAY=15
for i in $(seq 1 $MAX_RETRIES); do
echo "Attempt $i/$MAX_RETRIES..."
npm install -g "@localstack/lstk@${LSTK_VERSION}" && break
if [ "$i" -eq "$MAX_RETRIES" ]; then
echo "All $MAX_RETRIES attempts failed"
exit 1
fi
echo "Retrying in ${DELAY}s..."
sleep $DELAY
DELAY=$((DELAY * 2))
done
command -v lstk
- name: Install MSSQL ODBC and Tools
# Required for the 'web-app-sql-database' sample which uses 'sqlcmd' to
# initialize and verify the database schema in the local emulator.
# amd64 only: the sample is backed by mcr.microsoft.com/mssql/server, which has
# no arm64 image, so it never runs on the arm64 runners.
if: matrix.arch == 'amd64'
run: |
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
curl "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list" | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 mssql-tools18
echo "/opt/mssql-tools18/bin" >> "$GITHUB_PATH"
- name: "Run: ${{ matrix.name }}"
# Each job runs exactly one test. SPLITS equals the total test count, and SHARD
# is the 1-based index of this specific test, so run-samples.sh executes only it.
run: make test SHARD="${SHARD}" SPLITS="${SPLITS}"
env:
# Dynamic matrix values routed via env, not interpolated into the shell (template-injection)
SHARD: ${{ matrix.shard }}
SPLITS: ${{ matrix.splits }}
LOCALSTACK_AUTH_TOKEN: ${{ secrets.TEST_LOCALSTACK_AUTH_TOKEN }}
PURGE_DOCKER: "1"
- name: Get LocalStack Logs
# Captured on failure or success to provide a detailed audit trail of the emulator's activity.
if: always()
run: make logs