Notcurses-Native.git | .github/actions/package-and-upload/ | action.yml edit


name: package-and-upload
description: >-
  Write the third-party licensing kit into `bundle/`, gate the result
  against `resources/third-party.json`, then tar/zip `bundle/` into a
  platform-specific archive, compute its SHA256, stage everything
  under `artefacts/`, and upload as a GHA artifact for the
  release-publish job to collect.

  The licensing steps live here rather than in each build workflow on
  purpose: this action is the single choke point every lane goes
  through on its way to producing an archive, so a new lane cannot be
  added that ships an unaudited pack, and a lane cannot be edited to
  skip the gate without also losing its upload.

inputs:
  artifact-name:
    description: >-
      Archive basename without extension, e.g. `notcurses-macos-arm64`
      or `notcurses-linux-x86_64-musl`. Also used as the
      actions/upload-artifact name.
    required: true
  platform:
    description: >-
      `macos`, `linux` or `windows` — which set of basename patterns in
      resources/third-party.json describes this pack. Both Linux lanes
      pass `linux`: glibc and musl packs have the same file inventory
      because neither bundles a libc.
    required: true
  format:
    description: '`tar.gz` (Unix) or `zip` (Windows).'
    required: true
  shell:
    description: >-
      Shell to use for the packaging script. Defaults to `bash`. The
      Windows lane sets this to `msys2 {0}` so the `zip` utility
      installed via pacman is on PATH (Git Bash's PATH doesn't
      include it).
    required: false
    default: bash
  retention-days:
    description: How long the GHA artifact survives.
    required: false
    default: '14'

runs:
  using: composite
  steps:
    # Order is load-bearing: the kit is written INTO bundle/ first, so
    # the audit that follows sees exactly the file set the archive will
    # contain — including THIRD-PARTY.md and LICENSES/ themselves,
    # which the manifest accounts for under the notcurses-native
    # component. Auditing before generation would leave the two
    # documents unchecked, which is the one part of a licensing kit
    # nobody would notice going stale.
    - name: Write third-party licensing kit into the bundle
      shell: ${{ inputs.shell }}
      run: bash scripts/ci/emit-third-party-kit.sh '${{ inputs.platform }}' bundle

    # Release gate. Fails the lane if the pack contains a file no
    # manifest component describes (we would be redistributing a
    # binary whose licence nobody vetted) or is missing a component
    # the manifest promises is there (the pack is broken, or the
    # manifest has started lying). See the header of the script.
    - name: Audit bundle against the third-party manifest (release gate)
      shell: ${{ inputs.shell }}
      run: bash scripts/ci/audit-third-party.sh '${{ inputs.platform }}' bundle

    - name: Package archive (tar.gz)
      if: inputs.format == 'tar.gz'
      shell: ${{ inputs.shell }}
      run: |
        set -euxo pipefail
        artifact='${{ inputs.artifact-name }}.tar.gz'
        tar -czf "$artifact" -C bundle .
        if command -v sha256sum >/dev/null 2>&1; then
          sha256sum "$artifact" | tee "${artifact}.sha256"
        else
          # macOS doesn't ship sha256sum; shasum -a 256 is equivalent.
          shasum -a 256 "$artifact" | tee "${artifact}.sha256"
        fi
        mkdir -p artefacts
        mv "$artifact" "${artifact}.sha256" artefacts/

    - name: Package archive (zip)
      if: inputs.format == 'zip'
      shell: ${{ inputs.shell }}
      run: |
        set -euxo pipefail
        artifact='${{ inputs.artifact-name }}.zip'
        (cd bundle && zip -r "../$artifact" .)
        sha256sum "$artifact" | tee "${artifact}.sha256"
        mkdir -p artefacts
        mv "$artifact" "${artifact}.sha256" artefacts/

    - uses: actions/upload-artifact@v6
      with:
        name: ${{ inputs.artifact-name }}
        path: artefacts/
        retention-days: ${{ inputs.retention-days }}