Skip to content

publish

publish #3

Workflow file for this run

# Build and publish containers merged to master, on GitHub-hosted runners.
# A merge normally touches one container (enforced at PR time), but a direct push
# may touch several, so `detect` produces a matrix and `publish` fans out over it.
name: publish
on:
push:
branches: [master]
workflow_dispatch:
inputs:
container:
description: "Container name (top-level directory, e.g. aragorn)"
required: true
version:
description: "Version directory (e.g. 1.2.41)"
required: true
permissions:
contents: read
concurrency:
group: publish-${{ github.sha }}-${{ github.event.inputs.container }}
jobs:
detect:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.list.outputs.matrix }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine containers to publish
id: list
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
C='${{ github.event.inputs.container }}'
V='${{ github.event.inputs.version }}'
if [ ! -f "$C/$V/Dockerfile" ]; then
echo "No Dockerfile at $C/$V/Dockerfile"; exit 1
fi
echo "matrix=[{\"path\":\"$C/$V\",\"container\":\"$C\",\"version\":\"$V\"}]" >> "$GITHUB_OUTPUT"
echo "Manual publish: $C/$V"
else
git diff-tree --no-commit-id --name-only -r ${{ github.sha }} > changed_files.txt
echo "Changed files:"; cat changed_files.txt
python3 .github/scripts/validate.py list \
--changed-files changed_files.txt --out matrix.json
fi
publish:
needs: detect
if: ${{ needs.detect.outputs.matrix != '' && needs.detect.outputs.matrix != '[]' }}
runs-on: ubuntu-latest
permissions:
contents: write # create the Singularity release
security-events: write # upload the Trivy SARIF
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.detect.outputs.matrix) }}
env:
C: ${{ matrix.container }}
V: ${{ matrix.version }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- name: Build image (amd64) for validation
run: docker buildx build --load --platform linux/amd64 -t bcimg:local "$C/$V"
- name: Extract labels
run: docker inspect --format '{{json .Config.Labels}}' bcimg:local > labels.json
- name: Check labels and compute tag
id: check
run: |
python3 .github/scripts/validate.py check \
--container "$C" --version "$V" \
--labels labels.json --dockerfile "$C/$V/Dockerfile" --out report.json
- name: Run tests (test-cmds.txt)
run: |
TESTS="$C/$V/test-cmds.txt"
if [ ! -f "$TESTS" ]; then echo "No test-cmds.txt, skipping."; exit 0; fi
status=0
while IFS= read -r cmd || [ -n "$cmd" ]; do
[ -z "$cmd" ] && continue
echo "::group::TEST $cmd"
if docker run --rm bcimg:local $cmd; then echo "ok"; else echo "FAILED"; status=1; fi
echo "::endgroup::"
done < "$TESTS"
exit $status
- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push (multi-arch, amd64 fallback)
run: |
TAG="${{ steps.check.outputs.tag }}"
IMG="biocontainers/${C}:${TAG}"
# Many legacy BioContainers base images are amd64-only, so the arm64 leg
# fails fast at the FROM pull. Try multi-arch, fall back to amd64-only so
# amd64 always publishes and arm64 is added only when the base supports it.
if docker buildx build --platform linux/amd64,linux/arm64 --pull --push -t "$IMG" "$C/$V"; then
echo "Published multi-arch (amd64+arm64): $IMG"
echo "- \`$IMG\` — **multi-arch** (amd64 + arm64)" >> "$GITHUB_STEP_SUMMARY"
else
echo "arm64 build failed (base likely amd64-only); publishing amd64-only."
docker buildx build --platform linux/amd64 --pull --push -t "$IMG" "$C/$V"
echo "Published amd64-only: $IMG"
echo "- \`$IMG\` — **amd64-only** (base has no arm64)" >> "$GITHUB_STEP_SUMMARY"
fi
- name: Trivy security scan (report-only)
continue-on-error: true
uses: aquasecurity/trivy-action@0.35.0
with:
image-ref: biocontainers/${{ env.C }}:${{ steps.check.outputs.tag }}
format: sarif
output: trivy.sarif
severity: HIGH,CRITICAL
ignore-unfixed: true
- name: Upload Trivy results to Security tab
continue-on-error: true
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy.sarif
category: trivy-${{ env.C }}
- name: Set up Apptainer (Singularity)
uses: eWaterCycle/setup-apptainer@v2
- name: Convert to Singularity .sif
run: |
TAG="${{ steps.check.outputs.tag }}"
apptainer build "${C}_${TAG}.sif" "docker://biocontainers/${C}:${TAG}"
- name: Attach .sif to a GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.C }}-${{ steps.check.outputs.tag }}
name: ${{ env.C }} ${{ steps.check.outputs.tag }}
files: ${{ env.C }}_${{ steps.check.outputs.tag }}.sif
body: |
Singularity image for `biocontainers/${{ env.C }}:${{ steps.check.outputs.tag }}`.
Pull the container directly with:
`singularity pull docker://biocontainers/${{ env.C }}:${{ steps.check.outputs.tag }}`