diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9605ab..bf5a0a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -181,13 +181,6 @@ jobs: docker-build: name: docker-build needs: [ruff-lint, ruff-format, mypy-typecheck, unit-tests, integration-tests] - # Only run on merges to main, release branches, tags, or manual dispatch - if: | - github.event_name != 'pull_request' && - (github.ref == 'refs/heads/main' || - startsWith(github.ref, 'refs/heads/release/') || - startsWith(github.ref, 'refs/tags/v') || - github.event_name == 'workflow_dispatch') runs-on: ubuntu-24.04 steps: - name: Checkout repository @@ -201,29 +194,18 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v6 - with: - images: | - ${{ github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }} - tags: | - type=sha,format=long,prefix= - ref: ${{ github.sha }} - - - name: Build and load image + - name: Build and load Docker image (AMD64) uses: docker/build-push-action@v7 with: context: . push: false load: true platforms: linux/amd64 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + tags: "${{ github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }}:${{ github.sha }}" cache-from: type=gha,scope=docker-build cache-to: type=gha,mode=max,scope=docker-build - - name: Build ARM64 (cache only) + - name: Build Docker image (ARM64) uses: docker/build-push-action@v7 with: context: . @@ -232,14 +214,14 @@ jobs: cache-from: type=gha,scope=docker-build cache-to: type=gha,mode=max,scope=docker-build - - name: Smoke test image + - name: Smoke test Docker image run: | # Test CLI help docker run --rm ${{ github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }}:${{ github.sha }} --help # Test library import docker run --rm --entrypoint python ${{ github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }}:${{ github.sha }} -c "import pystormtracker as pst; print('Import success')" - - name: Vulnerability scan + - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@0.35.0 with: image-ref: "${{ github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }}:${{ github.sha }}" diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 353d3f8..92a4f78 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -11,16 +11,8 @@ on: workflow_dispatch: concurrency: - group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref_name }} - cancel-in-progress: ${{ !(github.event.workflow_run.event == 'release' || github.ref_type == 'tag') }} - -env: - # Publish to ORG on version tag/branch (v*.*), else to OWNER (personal) for merge to main/manual - # We check for both 'v' prefix and a dot to match the v?.?* requirement and avoid false positives - IS_STABLE: ${{ (github.event_name == 'workflow_run' && startsWith(github.event.workflow_run.head_branch, 'v') && contains(github.event.workflow_run.head_branch, '.')) || (github.event_name == 'workflow_dispatch' && (github.ref_type == 'tag' || (startsWith(github.ref_name, 'v') && contains(github.ref_name, '.')))) }} - - DOCKER_HUB_REPO: docker.io/${{ env.IS_STABLE == 'true' && vars.DOCKER_ORG_NAME || github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }} - GHCR_REPO: ghcr.io/${{ env.IS_STABLE == 'true' && vars.DOCKER_ORG_NAME || github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }} + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build-and-push: @@ -72,33 +64,13 @@ jobs: uses: docker/metadata-action@v6 with: images: | - ${{ env.DOCKER_HUB_REPO }} - ${{ env.GHCR_REPO }} - # Determine the symbolic ref to get the correct tags (semver/branch) - ref: >- - ${{ - github.event_name == 'workflow_run' - ? ( - (github.event.workflow_run.event == 'release' || startsWith(github.event.workflow_run.head_branch, 'v')) - ? format('refs/tags/{0}', github.event.workflow_run.head_branch) - : format('refs/heads/{0}', github.event.workflow_run.head_branch) - ) - : github.ref - }} + ${{ (startsWith(github.event.workflow_run.head_branch || github.ref_name, 'v')) && vars.DOCKER_ORG_NAME || github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }} + ghcr.io/${{ (startsWith(github.event.workflow_run.head_branch || github.ref_name, 'v')) && vars.DOCKER_ORG_NAME || github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }} tags: | - # Tag with 'latest' for main branch (used for personal repo/edge) - type=raw,value=latest,enable=${{ (github.event_name == 'workflow_run' && github.event.workflow_run.head_branch == 'main') || (github.event_name != 'workflow_run' && github.ref == 'refs/heads/main') }},priority=1000 - # Tag with 'edge' only for main branch builds - type=edge,branch=main,priority=900 - # Semver tags for releases (includes 'latest') - type=semver,pattern=latest,priority=1000 - type=semver,pattern={{version}},priority=800 - type=semver,pattern={{major}}.{{minor}},priority=700 - type=semver,pattern={{major}},enable=${{ !startsWith(github.ref_name, 'v0') }},priority=700 - # Branch tag for all branches except main - type=ref,event=branch,enable=${{ github.ref_name != 'main' && !startsWith(github.ref_name, 'v') }},priority=600 - # Always tag with short SHA - type=sha,format=short,prefix=,priority=100 + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || github.event.workflow_run.head_branch == 'main' }} + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,format=short,prefix= - name: Build and push Docker image id: push @@ -108,7 +80,7 @@ jobs: push: true provenance: false sbom: false - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha,scope=docker-build @@ -117,7 +89,7 @@ jobs: - name: Attest Provenance (Docker Hub) uses: actions/attest@v4 with: - subject-name: ${{ env.DOCKER_HUB_REPO }} + subject-name: ${{ (startsWith(github.event.workflow_run.head_branch || github.ref_name, 'v')) && vars.DOCKER_ORG_NAME || github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true @@ -132,7 +104,7 @@ jobs: - name: Attest SBOM (Docker Hub) uses: actions/attest@v4 with: - subject-name: ${{ env.DOCKER_HUB_REPO }} + subject-name: ${{ (startsWith(github.event.workflow_run.head_branch || github.ref_name, 'v')) && vars.DOCKER_ORG_NAME || github.repository_owner }}/${{ vars.DOCKER_IMAGE_NAME }} subject-digest: ${{ steps.push.outputs.digest }} sbom-path: 'sbom.cyclonedx.json' push-to-registry: true diff --git a/Dockerfile b/Dockerfile index fd543d0..40d189e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,15 +11,13 @@ ENV UV_COMPILE_BYTECODE=1 \ WORKDIR /app # Install build dependencies -# Only required for SHTns (amd64) -RUN if [ "$TARGETARCH" = "amd64" ]; then \ - apt-get update && apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ + g++ \ make \ libc6-dev \ libfftw3-dev \ - && rm -rf /var/lib/apt/lists/*; \ - fi + && rm -rf /var/lib/apt/lists/*; # Install uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ @@ -50,12 +48,9 @@ ARG TARGETARCH WORKDIR /app # Install runtime dependencies -# Only required for SHTns (amd64) -RUN if [ "$TARGETARCH" = "amd64" ]; then \ - apt-get update && apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get install -y --no-install-recommends \ libfftw3-double3 \ - && rm -rf /var/lib/apt/lists/*; \ - fi + && rm -rf /var/lib/apt/lists/*; # Create data directory for mounting RUN mkdir /data && chmod 777 /data