nftblock 0.1.2

Atomically apply CIDR lists with nftables netlink batches
Documentation
name: Release artifacts

on:
  workflow_call:
    inputs:
      repository:
        description: Repository to check out and use for GHCR image names
        required: true
        type: string
      ref:
        description: Commit, branch, or tag to check out
        required: true
        type: string
      version:
        description: Release version used in artifact and image names
        required: true
        type: string
      publish_artifacts:
        description: Whether to publish images and create attestations
        required: true
        type: boolean

permissions:
  contents: read

jobs:
  build-static-binary:
    name: Build static release binary
    runs-on: ubuntu-latest
    permissions:
      contents: read
      attestations: write
      artifact-metadata: write
      id-token: write
    steps:
      - name: Check out repository
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          repository: ${{ inputs.repository }}
          ref: ${{ inputs.ref }}
          fetch-depth: 0
          persist-credentials: false

      - name: Install native dependencies
        run: sudo apt-get update && sudo apt-get install -y build-essential libc6-dev libmnl-dev libnftnl-dev pkg-config

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
        with:
          toolchain: stable

      - name: Cache Cargo artifacts
        uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2

      - name: Install release tooling
        run: cargo install cargo-cyclonedx --version 0.5.9 --locked

      - name: Build static release binary
        env:
          CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS: -C target-feature=+crt-static
          PKG_CONFIG_ALL_STATIC: "1"
        run: cargo build --release --locked --bin nftblock --target x86_64-unknown-linux-gnu

      - name: Stage static binary archive
        id: static_asset
        env:
          VERSION: ${{ inputs.version }}
        run: |
          set -euxo pipefail
          mkdir -p dist/static
          archive="dist/static/nftblock-${VERSION}-x86_64-unknown-linux-gnu.tar.gz"
          tar -C target/x86_64-unknown-linux-gnu/release -czf "$archive" nftblock
          echo "archive=$archive" >> "$GITHUB_OUTPUT"

      - name: Generate static binary SBOM
        id: static_sbom
        run: |
          set -euxo pipefail
          cargo cyclonedx --format json --target x86_64-unknown-linux-gnu \
            --override-filename nftblock-x86_64-unknown-linux-gnu.cdx
          sbom="nftblock-x86_64-unknown-linux-gnu.cdx.json"
          test -f "$sbom"
          mv "$sbom" dist/static/
          echo "path=dist/static/$sbom" >> "$GITHUB_OUTPUT"

      - name: Attest binary provenance
        if: inputs.publish_artifacts
        uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
        with:
          subject-path: ${{ steps.static_asset.outputs.archive }}

      - name: Attest binary SBOM
        if: inputs.publish_artifacts
        uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
        with:
          subject-path: ${{ steps.static_asset.outputs.archive }}
          sbom-path: ${{ steps.static_sbom.outputs.path }}

      - name: Upload static binary artifact
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: static-binaries-x86_64-unknown-linux-gnu
          path: dist/static/
          if-no-files-found: error

  build-containers:
    name: Build container (${{ matrix.variant }})
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write
    strategy:
      fail-fast: false
      matrix:
        variant:
          - debian
          - alpine
    steps:
      - name: Check out repository
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          repository: ${{ inputs.repository }}
          ref: ${{ inputs.ref }}
          persist-credentials: false

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0

      - name: Log in to GitHub Container Registry
        if: inputs.publish_artifacts
        uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Generate image metadata
        id: metadata
        uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
        with:
          images: ghcr.io/${{ inputs.repository }}
          tags: |
            type=raw,value=${{ inputs.version }}-${{ matrix.variant }}
            type=raw,value=${{ matrix.variant }}

      - name: Build and optionally publish container
        uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
        with:
          context: .
          file: Dockerfile.${{ matrix.variant }}
          platforms: linux/amd64
          push: ${{ inputs.publish_artifacts }}
          tags: ${{ steps.metadata.outputs.tags }}
          labels: ${{ steps.metadata.outputs.labels }}
          cache-from: type=gha,scope=${{ matrix.variant }}
          cache-to: type=gha,mode=max,scope=${{ matrix.variant }}
          provenance: ${{ inputs.publish_artifacts && 'mode=max' || 'false' }}
          sbom: ${{ inputs.publish_artifacts }}