From d5cf60689e3975cd74e51ae84b19c429d60d4a69 Mon Sep 17 00:00:00 2001 From: Kyle Mendell Date: Sun, 26 Apr 2026 19:48:19 -0500 Subject: [PATCH] ci/cd: migrate github actions runners to depot runners (#1329) --- .github/workflows/backend-linter.yml | 5 +- .github/workflows/build-next.yml | 98 ++++++++++++++------- .github/workflows/e2e-tests.yml | 122 +++++++-------------------- .github/workflows/release.yml | 93 +++++++++++++------- .github/workflows/svelte-check.yml | 19 +++-- .github/workflows/unit-tests.yml | 18 ++-- .github/workflows/update-aaguids.yml | 5 +- depot.json | 1 + docker/Dockerfile | 18 ++-- tests/setup/docker-compose-s3.yml | 29 ++++--- tests/setup/localstack-init-s3.py | 22 +++++ 11 files changed, 239 insertions(+), 191 deletions(-) create mode 100644 depot.json create mode 100644 tests/setup/localstack-init-s3.py diff --git a/.github/workflows/backend-linter.yml b/.github/workflows/backend-linter.yml index a5a1839a..1765af38 100644 --- a/.github/workflows/backend-linter.yml +++ b/.github/workflows/backend-linter.yml @@ -17,14 +17,15 @@ permissions: pull-requests: read # Optional: allow write access to checks to allow the action to annotate code in the PR. checks: write + id-token: write jobs: golangci-lint: name: Run Golangci-lint - runs-on: ubuntu-latest + runs-on: depot-ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up Go uses: actions/setup-go@v6 diff --git a/.github/workflows/build-next.yml b/.github/workflows/build-next.yml index d531ff81..343a36d9 100644 --- a/.github/workflows/build-next.yml +++ b/.github/workflows/build-next.yml @@ -9,43 +9,40 @@ concurrency: group: build-next-image cancel-in-progress: true +permissions: + contents: read + packages: write + id-token: write + attestations: write + artifact-metadata: write + jobs: build-next: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - id-token: write - attestations: write + runs-on: depot-ubuntu-latest + + env: + CONTAINER_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/pocket-id + steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: 24 + cache: "pnpm" - name: Setup Go uses: actions/setup-go@v6 with: go-version-file: "backend/go.mod" - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Set DOCKER_IMAGE_NAME - run: | - # Lowercase REPO_OWNER which is required for containers - REPO_OWNER=${{ github.repository_owner }} - DOCKER_IMAGE_NAME="ghcr.io/${REPO_OWNER,,}/pocket-id" - echo "DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME}" >>${GITHUB_ENV} + - name: Set up Depot CLI + uses: depot/setup-action@v1 - name: Login to GitHub Container Registry uses: docker/login-action@v3 @@ -54,6 +51,40 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Container Image Metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.CONTAINER_IMAGE_NAME }} + tags: | + type=raw,value=next + labels: | + org.opencontainers.image.authors=Pocket ID + org.opencontainers.image.url=https://github.com/pocket-id/pocket-id + org.opencontainers.image.documentation=https://github.com/pocket-id/pocket-id/blob/main/README.md + org.opencontainers.image.source=https://github.com/pocket-id/pocket-id + org.opencontainers.image.version=next + org.opencontainers.image.licenses=BSD-2-Clause + org.opencontainers.image.ref.name=pocket-id + org.opencontainers.image.title=Pocket ID + + - name: Container Image Metadata + id: distroless-meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.CONTAINER_IMAGE_NAME }} + tags: | + type=raw,value=next-distroless + labels: | + org.opencontainers.image.authors=Pocket ID + org.opencontainers.image.url=https://github.com/pocket-id/pocket-id + org.opencontainers.image.documentation=https://github.com/pocket-id/pocket-id/blob/main/README.md + org.opencontainers.image.source=https://github.com/pocket-id/pocket-id + org.opencontainers.image.version=next-distroless + org.opencontainers.image.licenses=BSD-2-Clause + org.opencontainers.image.ref.name=pocket-id + org.opencontainers.image.title=Pocket ID + - name: Install frontend dependencies run: pnpm install --frozen-lockfile @@ -66,31 +97,40 @@ jobs: - name: Build and push container image id: build-push-image - uses: docker/build-push-action@v6 + uses: depot/build-push-action@v1 with: context: . + file: docker/Dockerfile-prebuilt platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.DOCKER_IMAGE_NAME }}:next - file: docker/Dockerfile-prebuilt + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + sbom: false + provenance: true + - name: Build and push container image (distroless) - uses: docker/build-push-action@v6 + uses: depot/build-push-action@v1 id: container-build-push-distroless with: context: . + file: docker/Dockerfile-distroless platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.DOCKER_IMAGE_NAME }}:next-distroless - file: docker/Dockerfile-distroless + tags: ${{ steps.distroless-meta.outputs.tags }} + labels: ${{ steps.distroless-meta.outputs.labels }} + sbom: false + provenance: true + - name: Container image attestation uses: actions/attest-build-provenance@v2 with: - subject-name: "${{ env.DOCKER_IMAGE_NAME }}" + subject-name: "${{ env.CONTAINER_IMAGE_NAME }}" subject-digest: ${{ steps.build-push-image.outputs.digest }} push-to-registry: true + - name: Container image attestation (distroless) uses: actions/attest-build-provenance@v2 with: - subject-name: "${{ env.DOCKER_IMAGE_NAME }}" + subject-name: "${{ env.CONTAINER_IMAGE_NAME }}" subject-digest: ${{ steps.container-build-push-distroless.outputs.digest }} push-to-registry: true diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index c0f46ca9..7cde9ebd 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -1,59 +1,27 @@ name: E2E Tests on: push: - branches: [main] + branches: [ main ] paths-ignore: - "docs/**" - "**.md" - ".github/**" pull_request: - branches: [main, breaking/**] + branches: [ main, breaking/** ] paths-ignore: - "docs/**" - "**.md" - ".github/**" +permissions: + contents: read + actions: write + id-token: write + jobs: - build: - if: github.event.pull_request.head.ref != 'i18n_crowdin' - timeout-minutes: 20 - permissions: - contents: read - actions: write - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and export - uses: docker/build-push-action@v6 - with: - context: . - file: docker/Dockerfile - push: false - load: false - tags: pocket-id:test - outputs: type=docker,dest=/tmp/docker-image.tar - build-args: BUILD_TAGS=e2etest - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Upload Docker image artifact - uses: actions/upload-artifact@v4 - with: - name: docker-image - path: /tmp/docker-image.tar - retention-days: 1 - test: if: github.event.pull_request.head.ref != 'i18n_crowdin' - permissions: - contents: read - actions: write - runs-on: ubuntu-latest - needs: build + runs-on: depot-ubuntu-24.04-32 strategy: fail-fast: false matrix: @@ -70,25 +38,33 @@ jobs: storage: database steps: - - uses: actions/checkout@v5 + - name: Checkout code + uses: actions/checkout@v6 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: 24 + cache: "pnpm" + + - name: Set up Depot CLI + uses: depot/setup-action@v1 + + - name: Set up Depot Docker builder + run: depot configure-docker - name: Cache Playwright Browsers - uses: actions/cache@v4 + uses: actions/cache@v5 id: playwright-cache with: path: ~/.cache/ms-playwright key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }} - name: Cache PostgreSQL Docker image - uses: actions/cache@v4 + uses: actions/cache@v5 id: postgres-cache with: path: /tmp/postgres-image.tar @@ -102,23 +78,8 @@ jobs: if: matrix.db == 'postgres' && steps.postgres-cache.outputs.cache-hit == 'true' run: docker load < /tmp/postgres-image.tar - - name: Cache LLDAP Docker image - uses: actions/cache@v4 - id: lldap-cache - with: - path: /tmp/lldap-image.tar - key: lldap-stable-${{ runner.os }} - - name: Pull and save LLDAP image - if: steps.lldap-cache.outputs.cache-hit != 'true' - run: | - docker pull lldap/lldap:2025-05-19 - docker save lldap/lldap:2025-05-19 > /tmp/lldap-image.tar - - name: Load LLDAP image - if: steps.lldap-cache.outputs.cache-hit == 'true' - run: docker load < /tmp/lldap-image.tar - - name: Cache SCIM Test Server Docker image - uses: actions/cache@v4 + uses: actions/cache@v5 id: scim-cache with: path: /tmp/scim-test-server-image.tar @@ -134,45 +95,20 @@ jobs: - name: Cache Localstack S3 Docker image if: matrix.storage == 's3' - uses: actions/cache@v4 + uses: actions/cache@v5 id: s3-cache with: path: /tmp/localstack-s3-image.tar - key: localstack-s3-latest-${{ runner.os }} + key: localstack-4.14.0-${{ runner.os }} - name: Pull and save Localstack S3 image if: matrix.storage == 's3' && steps.s3-cache.outputs.cache-hit != 'true' run: | - docker pull localstack/localstack:s3-latest - docker save localstack/localstack:s3-latest > /tmp/localstack-s3-image.tar + docker pull localstack/localstack:4.14.0 + docker save localstack/localstack:4.14.0 > /tmp/localstack-s3-image.tar - name: Load Localstack S3 image if: matrix.storage == 's3' && steps.s3-cache.outputs.cache-hit == 'true' run: docker load < /tmp/localstack-s3-image.tar - - name: Cache AWS CLI Docker image - if: matrix.storage == 's3' - uses: actions/cache@v4 - id: aws-cli-cache - with: - path: /tmp/aws-cli-image.tar - key: aws-cli-latest-${{ runner.os }} - - name: Pull and save AWS CLI image - if: matrix.storage == 's3' && steps.aws-cli-cache.outputs.cache-hit != 'true' - run: | - docker pull amazon/aws-cli:latest - docker save amazon/aws-cli:latest > /tmp/aws-cli-image.tar - - name: Load AWS CLI image - if: matrix.storage == 's3' && steps.aws-cli-cache.outputs.cache-hit == 'true' - run: docker load < /tmp/aws-cli-image.tar - - - name: Download Docker image artifact - uses: actions/download-artifact@v4 - with: - name: docker-image - path: /tmp - - - name: Load Docker image - run: docker load -i /tmp/docker-image.tar - - name: Install test dependencies run: pnpm --filter pocket-id-tests install --frozen-lockfile @@ -198,7 +134,7 @@ jobs: DOCKER_COMPOSE_FILE=docker-compose-s3.yml fi - docker compose -f "$DOCKER_COMPOSE_FILE" up -d + docker compose -f "$DOCKER_COMPOSE_FILE" up -d --build { LOG_FILE="/tmp/backend.log" @@ -219,7 +155,7 @@ jobs: run: pnpm exec playwright test - name: Upload Test Report - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: always() && github.event.pull_request.head.ref != 'i18n_crowdin' with: name: playwright-report-${{ matrix.db }}-${{ matrix.storage }} @@ -228,7 +164,7 @@ jobs: retention-days: 15 - name: Upload Backend Test Report - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: always() && github.event.pull_request.head.ref != 'i18n_crowdin' with: name: backend-${{ matrix.db }}-${{ matrix.storage }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cfd94006..3f5a41d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,42 +5,47 @@ on: tags: - "v*.*.*" +permissions: + contents: write + packages: write + attestations: write + id-token: write + artifact-metadata: write + jobs: build: - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - attestations: write - id-token: write + runs-on: depot-ubuntu-24.04-16 + + env: + CONTAINER_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/pocket-id + steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v6 + - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v5 + + - name: Set up Depot CLI + uses: depot/setup-action@v1 + - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: 24 + cache: "pnpm" + - uses: actions/setup-go@v6 with: go-version-file: "backend/go.mod" - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Set DOCKER_IMAGE_NAME - run: | - # Lowercase REPO_OWNER which is required for containers - REPO_OWNER=${{ github.repository_owner }} - DOCKER_IMAGE_NAME="ghcr.io/${REPO_OWNER,,}/pocket-id" - echo "DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME}" >>${GITHUB_ENV} + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{github.repository_owner}} password: ${{secrets.GITHUB_TOKEN}} + - name: Docker metadata id: meta uses: docker/metadata-action@v5 @@ -51,59 +56,89 @@ jobs: type=semver,pattern={{version}},prefix=v type=semver,pattern={{major}}.{{minor}},prefix=v type=semver,pattern={{major}},prefix=v + labels: | + org.opencontainers.image.authors=Pocket ID + org.opencontainers.image.url=https://github.com/pocket-id/pocket-id + org.opencontainers.image.documentation=https://github.com/pocket-id/pocket-id/blob/main/README.md + org.opencontainers.image.source=https://github.com/pocket-id/pocket-id + org.opencontainers.image.version=next + org.opencontainers.image.licenses=BSD-2-Clause + org.opencontainers.image.ref.name=pocket-id + org.opencontainers.image.title=Pocket ID + - name: Docker metadata (distroless) id: meta-distroless uses: docker/metadata-action@v5 with: images: | - ${{ env.DOCKER_IMAGE_NAME }} + ${{ env.CONTAINER_IMAGE_NAME }} flavor: | suffix=-distroless,onlatest=true tags: | type=semver,pattern={{version}},prefix=v type=semver,pattern={{major}}.{{minor}},prefix=v type=semver,pattern={{major}},prefix=v + labels: | + org.opencontainers.image.authors=Pocket ID + org.opencontainers.image.url=https://github.com/pocket-id/pocket-id + org.opencontainers.image.documentation=https://github.com/pocket-id/pocket-id/blob/main/README.md + org.opencontainers.image.source=https://github.com/pocket-id/pocket-id + org.opencontainers.image.version=next-distroless + org.opencontainers.image.licenses=BSD-2-Clause + org.opencontainers.image.ref.name=pocket-id + org.opencontainers.image.title=Pocket ID + - name: Install frontend dependencies run: pnpm --filter pocket-id-frontend install --frozen-lockfile + - name: Build frontend run: pnpm --filter pocket-id-frontend build - name: Build binaries run: sh scripts/development/build-binaries.sh + - name: Build and push container image - uses: docker/build-push-action@v6 + uses: depot/build-push-action@v1 id: container-build-push with: context: . + file: docker/Dockerfile-prebuilt platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - file: docker/Dockerfile-prebuilt + sbom: false + provenance: true + - name: Build and push container image (distroless) - uses: docker/build-push-action@v6 + uses: depot/build-push-action@v1 id: container-build-push-distroless with: context: . + file: docker/Dockerfile-distroless platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta-distroless.outputs.tags }} labels: ${{ steps.meta-distroless.outputs.labels }} - file: docker/Dockerfile-distroless + sbom: false + provenance: true + - name: Binary attestation uses: actions/attest-build-provenance@v2 with: subject-path: "backend/.bin/pocket-id-**" + - name: Container image attestation uses: actions/attest-build-provenance@v2 with: - subject-name: "${{ env.DOCKER_IMAGE_NAME }}" + subject-name: "${{ env.CONTAINER_IMAGE_NAME }}" subject-digest: ${{ steps.container-build-push.outputs.digest }} push-to-registry: true + - name: Container image attestation (distroless) uses: actions/attest-build-provenance@v2 with: - subject-name: "${{ env.DOCKER_IMAGE_NAME }}" + subject-name: "${{ env.CONTAINER_IMAGE_NAME }}" subject-digest: ${{ steps.container-build-push-distroless.outputs.digest }} push-to-registry: true - name: Upload binaries to release @@ -112,14 +147,12 @@ jobs: run: gh release upload ${{ github.ref_name }} backend/.bin/* publish-release: - runs-on: ubuntu-latest + runs-on: depot-ubuntu-latest needs: [build] - permissions: - contents: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Mark release as published run: gh release edit ${{ github.ref_name }} --draft=false diff --git a/.github/workflows/svelte-check.yml b/.github/workflows/svelte-check.yml index 9a0c761c..2f14fc18 100644 --- a/.github/workflows/svelte-check.yml +++ b/.github/workflows/svelte-check.yml @@ -21,28 +21,31 @@ on: - "frontend/svelte.config.js" workflow_dispatch: +permissions: + contents: read + checks: write + pull-requests: write + id-token: write + jobs: type-check: name: Run Svelte Check # Don't run on dependabot branches if: github.actor != 'dependabot[bot]' - runs-on: ubuntu-latest - permissions: - contents: read - checks: write - pull-requests: write + runs-on: depot-ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: 24 + cache: "pnpm" - name: Install dependencies run: pnpm --filter pocket-id-frontend install --frozen-lockfile diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index ca2b36a0..55cf9c54 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -1,22 +1,24 @@ name: Unit Tests on: push: - branches: [main] + branches: [ main ] paths: - "backend/**" pull_request: - branches: [main] + branches: [ main ] paths: - "backend/**" +permissions: + contents: read + id-token: write + actions: write + jobs: test-backend: - permissions: - contents: read - actions: write - runs-on: ubuntu-latest + runs-on: depot-ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: go-version-file: "backend/go.mod" @@ -30,7 +32,7 @@ jobs: run: | set -e -o pipefail go test -tags=exclude_frontend -v ./... | tee /tmp/TestResults.log - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 if: always() with: name: backend-unit-tests diff --git a/.github/workflows/update-aaguids.yml b/.github/workflows/update-aaguids.yml index 18778b05..fbe42e13 100644 --- a/.github/workflows/update-aaguids.yml +++ b/.github/workflows/update-aaguids.yml @@ -8,14 +8,15 @@ on: permissions: contents: write pull-requests: write + id-token: write jobs: update-aaguids: - runs-on: ubuntu-latest + runs-on: depot-ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Fetch JSON data run: | diff --git a/depot.json b/depot.json new file mode 100644 index 00000000..028fecaf --- /dev/null +++ b/depot.json @@ -0,0 +1 @@ +{ "id": "c36t29j6bz" } diff --git a/docker/Dockerfile b/docker/Dockerfile index 33eee959..34b1baf2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1.7 + # This file uses multi-stage builds to build the application from source, including the front-end # Tags passed to "go build" @@ -9,27 +11,33 @@ RUN corepack enable WORKDIR /build -COPY pnpm-workspace.yaml pnpm-lock.yaml ./ +COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./ COPY frontend/package.json ./frontend/ -RUN pnpm --filter pocket-id-frontend install --frozen-lockfile +RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ + pnpm --filter pocket-id-frontend install --frozen-lockfile COPY ./frontend ./frontend/ -RUN BUILD_OUTPUT_PATH=dist pnpm --filter pocket-id-frontend run build +RUN --mount=type=cache,target=/build/frontend/node_modules/.vite \ + --mount=type=cache,target=/build/frontend/.svelte-kit \ + BUILD_OUTPUT_PATH=dist pnpm --filter pocket-id-frontend run build # Stage 2: Build Backend FROM golang:1.26-alpine AS backend-builder ARG BUILD_TAGS WORKDIR /build COPY ./backend/go.mod ./backend/go.sum ./ -RUN go mod download +RUN --mount=type=cache,target=/go/pkg/mod \ + go mod download COPY ./backend ./ COPY --from=frontend-builder /build/frontend/dist ./frontend/dist COPY .version .version WORKDIR /build/cmd -RUN VERSION=$(cat /build/.version) \ +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + VERSION=$(cat /build/.version) && \ CGO_ENABLED=0 \ GOOS=linux \ go build \ diff --git a/tests/setup/docker-compose-s3.yml b/tests/setup/docker-compose-s3.yml index 533afee9..13ab0d9b 100644 --- a/tests/setup/docker-compose-s3.yml +++ b/tests/setup/docker-compose-s3.yml @@ -8,22 +8,23 @@ services: file: docker-compose.yml service: scim-test-server localstack-s3: - image: localstack/localstack:s3-latest - healthcheck: - test: ["CMD", "curl", "-f", "http://localstack-s3:4566"] - interval: 1s - timeout: 3s - retries: 10 - create-bucket: - image: amazon/aws-cli:latest + image: localstack/localstack:4.14.0 environment: + SERVICES: s3 AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_DEFAULT_REGION: us-east-1 - depends_on: - localstack-s3: - condition: service_healthy - entrypoint: "aws --endpoint-url=http://localstack-s3:4566 s3 mb s3://pocket-id-test" + volumes: + - ./localstack-init-s3.py:/etc/localstack/init/ready.d/10-init-s3.py + healthcheck: + test: + [ + "CMD-SHELL", + 'curl -fs http://localstack-s3:4566/_localstack/init/ready | grep -q ''"completed": true''', + ] + interval: 1s + timeout: 3s + retries: 10 pocket-id: extends: file: docker-compose.yml @@ -37,8 +38,8 @@ services: S3_SECRET_ACCESS_KEY: test S3_FORCE_PATH_STYLE: true depends_on: - create-bucket: - condition: service_completed_successfully + localstack-s3: + condition: service_healthy volumes: pocket-id-test-data: diff --git a/tests/setup/localstack-init-s3.py b/tests/setup/localstack-init-s3.py new file mode 100644 index 00000000..8c7c8671 --- /dev/null +++ b/tests/setup/localstack-init-s3.py @@ -0,0 +1,22 @@ +import boto3 +from botocore.exceptions import ClientError + +BUCKET_NAME = "pocket-id-test" + + +def main() -> None: + s3 = boto3.client( + "s3", + endpoint_url="http://localhost:4566", + aws_access_key_id="test", + aws_secret_access_key="test", + region_name="us-east-1", + ) + + try: + s3.head_bucket(Bucket=BUCKET_NAME) + except ClientError: + s3.create_bucket(Bucket=BUCKET_NAME) + + +main()