9.10.2__lts-24.11__2.11.0.0 #100
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # https://docs.github.com/en/actions/use-cases-and-examples/publishing-packages/publishing-docker-images | |
| # | |
| name: Build and Push | |
| on: | |
| push: | |
| branches: ['*'] | |
| tags: ['*'] | |
| workflow_dispatch: | |
| # Prevent concurrent runs for the same ref to avoid race conditions | |
| concurrency: | |
| group: ${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: lcamel/haskell-devcontainer | |
| IMAGE_NAME_TEMP: lcamel/haskell-devcontainer-temp | |
| jobs: | |
| # Validate ref name before starting any builds | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 # Need script from repo | |
| - name: Validate ref name | |
| run: ./.github/scripts/validate-ref.sh "${{ github.ref_name }}" "${{ github.ref_type }}" | |
| # Build and push images for each architecture | |
| build: | |
| needs: validate | |
| strategy: | |
| matrix: | |
| include: | |
| - platform: linux/amd64 | |
| runner: ubuntu-24.04 | |
| arch: amd64 | |
| - platform: linux/arm64 | |
| runner: ubuntu-24.04-arm | |
| arch: arm64 | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: docker/ | |
| push: true | |
| platforms: ${{ matrix.platform }} | |
| pull: true | |
| no-cache: ${{ github.ref_type == 'tag' }} | |
| cache-from: type=gha,scope=${{ matrix.arch }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.arch }} | |
| outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME_TEMP }},push-by-digest=true,name-canonical=true | |
| - name: Export digest | |
| run: | | |
| mkdir -p /tmp/digests | |
| echo "${{ steps.build.outputs.digest }}" > /tmp/digests/${{ matrix.arch }} | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: digest-${{ matrix.arch }} | |
| path: /tmp/digests/${{ matrix.arch }} | |
| # Create and push a single multi-architecture image (manifest) | |
| merge: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: /tmp/digests | |
| pattern: digest-* | |
| merge-multiple: true | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create and push multi-arch manifest to temp package | |
| run: | | |
| AMD64_DIGEST=$(cat /tmp/digests/amd64) | |
| ARM64_DIGEST=$(cat /tmp/digests/arm64) | |
| IMAGE_TAG="${{ github.ref_name }}" | |
| echo "Image Tag: ${IMAGE_TAG}" | |
| docker buildx imagetools create \ | |
| -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_TEMP }}:${IMAGE_TAG} \ | |
| --annotation "index:org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ | |
| --annotation "index:org.opencontainers.image.description=Ready-to-use Haskell environment with GHC, Stackage, and HLS" \ | |
| --annotation "index:org.opencontainers.image.licenses=MIT" \ | |
| --annotation "index:org.opencontainers.image.revision=${{ github.sha }}" \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_TEMP }}@${AMD64_DIGEST} \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_TEMP }}@${ARM64_DIGEST} | |
| # Run smoke tests against the multi-arch image | |
| test: | |
| needs: merge | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-24.04 | |
| platform: linux/amd64 | |
| - runner: ubuntu-24.04-arm | |
| platform: linux/arm64 | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Run smoke test | |
| run: | | |
| FULL_IMAGE_NAME="${{ env.REGISTRY }}/${{ env.IMAGE_NAME_TEMP }}:${{ github.ref_name }}" | |
| echo "Testing ${FULL_IMAGE_NAME} on ${{ matrix.platform }}..." | |
| docker pull "${FULL_IMAGE_NAME}" | |
| # GITHUB_TOKEN: "stack new" uses GitHub API to fetch templates, may hit rate limits without auth | |
| # See: https://github.com/commercialhaskell/stack/issues/6034 | |
| docker run --rm \ | |
| --platform ${{ matrix.platform }} \ | |
| -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ | |
| -v ${{ github.workspace }}/.github/scripts/smoke-test.sh:/tmp/smoke-test.sh \ | |
| -v ${{ github.workspace }}/docker/haskell-versions.env:/tmp/haskell-versions.env \ | |
| -w /tmp \ | |
| "${FULL_IMAGE_NAME}" \ | |
| bash -li /tmp/smoke-test.sh | |
| # Promote the image to production upon successful tests (tags only; branch builds remain in temp) | |
| promote: | |
| needs: [merge, test] | |
| if: github.ref_type == 'tag' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write | |
| steps: | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Promote image from temp package to production | |
| run: | | |
| IMAGE_TAG="${{ github.ref_name }}" | |
| echo "Promoting from temp package to production..." | |
| echo "Source: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_TEMP }}:${IMAGE_TAG}" | |
| echo "Target: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${IMAGE_TAG}" | |
| docker buildx imagetools create \ | |
| -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${IMAGE_TAG} \ | |
| --annotation "index:org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ | |
| --annotation "index:org.opencontainers.image.description=Ready-to-use Haskell environment with GHC, Stackage, and HLS" \ | |
| --annotation "index:org.opencontainers.image.licenses=MIT" \ | |
| --annotation "index:org.opencontainers.image.revision=${{ github.sha }}" \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_TEMP }}:${IMAGE_TAG} | |
| echo "Successfully promoted to ${IMAGE_TAG}" | |
| echo "Note: Temp package versions will be cleaned up by scheduled cleanup workflow" | |
| # Update floating tags (latest, ghc-X.Y.Z, stackage-lts-X.Y) | |
| # This runs sequentially to avoid race conditions. | |
| tag-floating: | |
| needs: promote | |
| runs-on: ubuntu-latest | |
| # Ensure sequential execution to prevent race conditions. | |
| concurrency: | |
| group: update-floating-tags-lock | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 # Need checkout to get the script | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Update Floating Tags | |
| run: | | |
| TARGET_TAG="${{ github.ref_name }}" | |
| echo "Target Tag: $TARGET_TAG" | |
| # 1. Fetch all existing tags from Registry | |
| echo "Fetching all tags from registry..." | |
| REMOTE_TAGS=$(docker run --rm \ | |
| -v $HOME/.docker:/root/.docker \ | |
| gcr.io/go-containerregistry/crane:latest \ | |
| ls ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}) | |
| # 2. Calculate which tags need to be updated | |
| TAGS_TO_UPDATE=$(echo "$REMOTE_TAGS" | ./.github/scripts/calculate-floating-tags.sh "$TARGET_TAG") | |
| echo "Tags to update:" | |
| echo "$TAGS_TO_UPDATE" | |
| # 3. Apply updates | |
| if [ -n "$TAGS_TO_UPDATE" ]; then | |
| TAG_ARGS="" | |
| for tag in $TAGS_TO_UPDATE; do | |
| echo "Queueing update for: $tag" | |
| TAG_ARGS="$TAG_ARGS -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$tag" | |
| done | |
| echo "Applying updates..." | |
| docker buildx imagetools create $TAG_ARGS \ | |
| --annotation "index:org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ | |
| --annotation "index:org.opencontainers.image.description=Ready-to-use Haskell environment with GHC, Stackage, and HLS" \ | |
| --annotation "index:org.opencontainers.image.licenses=MIT" \ | |
| --annotation "index:org.opencontainers.image.revision=${{ github.sha }}" \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$TARGET_TAG | |
| else | |
| echo "No floating tags to update." | |
| fi |