diff --git a/.github/workflows/zig-ci.yml b/.github/workflows/zig-ci.yml index 025ebb3..c5d1e98 100644 --- a/.github/workflows/zig-ci.yml +++ b/.github/workflows/zig-ci.yml @@ -27,6 +27,11 @@ on: {"os":"macos-latest","target":"macos-aarch64","zig_target":"aarch64-macos"}, {"os":"windows-latest","target":"windows-x86_64","zig_target":"x86_64-windows"} ] + extra_targets_json: + description: JSON array of project-specific target entries appended to targets_json. + required: false + type: string + default: "[]" node_version: description: Optional Node.js version to install before custom commands. required: false @@ -82,8 +87,34 @@ env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" jobs: + targets: + name: Resolve target matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.merge.outputs.matrix }} + + steps: + - name: Merge target matrices + id: merge + env: + TARGETS_JSON: ${{ inputs.targets_json }} + EXTRA_TARGETS_JSON: ${{ inputs.extra_targets_json }} + run: | + merged="$(jq -cn \ + --argjson targets "${TARGETS_JSON}" \ + --argjson extra "${EXTRA_TARGETS_JSON}" \ + '$targets + $extra')" + jq -e 'type == "array" and length > 0 and all(.[]; type == "object" and has("os") and has("target") and has("zig_target") and ((has("build_args") | not) or (.build_args | type == "string")))' \ + <<< "${merged}" >/dev/null + if [ "$(jq '[.[].target] | length' <<< "${merged}")" -ne "$(jq '[.[].target] | unique | length' <<< "${merged}")" ]; then + echo "target names must be unique across targets_json and extra_targets_json" >&2 + exit 1 + fi + echo "matrix=${merged}" >> "$GITHUB_OUTPUT" + test: name: ${{ matrix.target }} + needs: targets runs-on: ${{ matrix.os }} defaults: run: @@ -91,7 +122,7 @@ jobs: strategy: fail-fast: false matrix: - include: ${{ fromJson(inputs.targets_json) }} + include: ${{ fromJson(needs.targets.outputs.matrix) }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -159,15 +190,18 @@ jobs: - name: Build ReleaseSmall env: EXTRA_BUILD_ARGS: ${{ inputs.build_args }} + TARGET_BUILD_ARGS: ${{ matrix.build_args }} run: | zig_args=( -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseSmall ) - if [ -n "${EXTRA_BUILD_ARGS}" ]; then - read -r -a extra_args <<< "${EXTRA_BUILD_ARGS}" - zig_args+=("${extra_args[@]}") - fi + for build_args in "${EXTRA_BUILD_ARGS}" "${TARGET_BUILD_ARGS}"; do + if [ -n "${build_args}" ]; then + read -r -a extra_args <<< "${build_args}" + zig_args+=("${extra_args[@]}") + fi + done zig build "${zig_args[@]}" - name: Run E2E command diff --git a/.github/workflows/zig-nightly.yml b/.github/workflows/zig-nightly.yml index 6124941..64f2e45 100644 --- a/.github/workflows/zig-nightly.yml +++ b/.github/workflows/zig-nightly.yml @@ -46,6 +46,11 @@ on: {"os":"windows-latest","target":"windows-x86_64","zig_target":"x86_64-windows","zig_cpu":"","ext":".exe"}, {"os":"windows-latest","target":"windows-aarch64","zig_target":"aarch64-windows","zig_cpu":"","ext":".exe"} ] + extra_targets_json: + description: JSON array of project-specific nightly targets appended to targets_json. + required: false + type: string + default: "[]" node_version: description: Optional Node.js version to install before custom commands. required: false @@ -114,6 +119,7 @@ jobs: short_sha: ${{ steps.version.outputs.short_sha }} artifact_prefix: ${{ steps.version.outputs.artifact_prefix }} built_at: ${{ steps.version.outputs.built_at }} + matrix: ${{ steps.targets.outputs.matrix }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -138,6 +144,24 @@ jobs: echo "value=nightly-${build_date}-${short_sha}" >> "$GITHUB_OUTPUT" echo "artifact_prefix=${artifact_prefix}" >> "$GITHUB_OUTPUT" + - name: Merge target matrices + id: targets + env: + TARGETS_JSON: ${{ inputs.targets_json }} + EXTRA_TARGETS_JSON: ${{ inputs.extra_targets_json }} + run: | + merged="$(jq -cn \ + --argjson targets "${TARGETS_JSON}" \ + --argjson extra "${EXTRA_TARGETS_JSON}" \ + '$targets + $extra')" + jq -e 'type == "array" and length > 0 and all(.[]; type == "object" and has("os") and has("target") and has("zig_target") and ((has("build_args") | not) or (.build_args | type == "string")))' \ + <<< "${merged}" >/dev/null + if [ "$(jq '[.[].target] | length' <<< "${merged}")" -ne "$(jq '[.[].target] | unique | length' <<< "${merged}")" ]; then + echo "target names must be unique across targets_json and extra_targets_json" >&2 + exit 1 + fi + echo "matrix=${merged}" >> "$GITHUB_OUTPUT" + - name: Fetch previous successful workflow runs env: GH_TOKEN: ${{ github.token }} @@ -181,7 +205,7 @@ jobs: strategy: fail-fast: false matrix: - include: ${{ fromJson(inputs.targets_json) }} + include: ${{ fromJson(needs.preflight.outputs.matrix) }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -256,6 +280,7 @@ jobs: env: ANDROID_API_LEVEL: ${{ inputs.android_api_level }} EXTRA_BUILD_ARGS: ${{ inputs.build_args }} + TARGET_BUILD_ARGS: ${{ matrix.build_args }} run: | zig_target="${{ matrix.zig_target }}" if [[ "${{ matrix.target }}" == android-* ]]; then @@ -273,10 +298,12 @@ jobs: if [[ "${{ matrix.target }}" == android-* ]]; then zig_args+=(--libc "${ZIG_ANDROID_LIBC_FILE}") fi - if [ -n "${EXTRA_BUILD_ARGS}" ]; then - read -r -a extra_args <<< "${EXTRA_BUILD_ARGS}" - zig_args+=("${extra_args[@]}") - fi + for build_args in "${EXTRA_BUILD_ARGS}" "${TARGET_BUILD_ARGS}"; do + if [ -n "${build_args}" ]; then + read -r -a extra_args <<< "${build_args}" + zig_args+=("${extra_args[@]}") + fi + done zig build "${zig_args[@]}" - name: Package nightly artifact diff --git a/.github/workflows/zig-release.yml b/.github/workflows/zig-release.yml index 4097184..74753fb 100644 --- a/.github/workflows/zig-release.yml +++ b/.github/workflows/zig-release.yml @@ -46,6 +46,11 @@ on: {"os":"windows-latest","target":"windows-x86_64","zig_target":"x86_64-windows","zig_cpu":"","ext":".exe"}, {"os":"windows-latest","target":"windows-aarch64","zig_target":"aarch64-windows","zig_cpu":"","ext":".exe"} ] + extra_targets_json: + description: JSON array of project-specific release targets appended to targets_json. + required: false + type: string + default: "[]" node_version: description: Optional Node.js version to install before custom commands. required: false @@ -104,8 +109,34 @@ env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" jobs: + targets: + name: Resolve target matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.merge.outputs.matrix }} + + steps: + - name: Merge target matrices + id: merge + env: + TARGETS_JSON: ${{ inputs.targets_json }} + EXTRA_TARGETS_JSON: ${{ inputs.extra_targets_json }} + run: | + merged="$(jq -cn \ + --argjson targets "${TARGETS_JSON}" \ + --argjson extra "${EXTRA_TARGETS_JSON}" \ + '$targets + $extra')" + jq -e 'type == "array" and length > 0 and all(.[]; type == "object" and has("os") and has("target") and has("zig_target") and ((has("build_args") | not) or (.build_args | type == "string")))' \ + <<< "${merged}" >/dev/null + if [ "$(jq '[.[].target] | length' <<< "${merged}")" -ne "$(jq '[.[].target] | unique | length' <<< "${merged}")" ]; then + echo "target names must be unique across targets_json and extra_targets_json" >&2 + exit 1 + fi + echo "matrix=${merged}" >> "$GITHUB_OUTPUT" + build: name: Build (${{ matrix.target }}) + needs: targets runs-on: ${{ matrix.os }} defaults: run: @@ -113,7 +144,7 @@ jobs: strategy: fail-fast: false matrix: - include: ${{ fromJson(inputs.targets_json) }} + include: ${{ fromJson(needs.targets.outputs.matrix) }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -206,6 +237,7 @@ jobs: env: ANDROID_API_LEVEL: ${{ inputs.android_api_level }} EXTRA_BUILD_ARGS: ${{ inputs.build_args }} + TARGET_BUILD_ARGS: ${{ matrix.build_args }} run: | zig_target="${{ matrix.zig_target }}" if [[ "${{ matrix.target }}" == android-* ]]; then @@ -222,10 +254,12 @@ jobs: if [[ "${{ matrix.target }}" == android-* ]]; then zig_args+=(--libc "${ZIG_ANDROID_LIBC_FILE}") fi - if [ -n "${EXTRA_BUILD_ARGS}" ]; then - read -r -a extra_args <<< "${EXTRA_BUILD_ARGS}" - zig_args+=("${extra_args[@]}") - fi + for build_args in "${EXTRA_BUILD_ARGS}" "${TARGET_BUILD_ARGS}"; do + if [ -n "${build_args}" ]; then + read -r -a extra_args <<< "${build_args}" + zig_args+=("${extra_args[@]}") + fi + done zig build "${zig_args[@]}" - name: Upload artifact diff --git a/README.md b/README.md index 5ad05ee..5624dce 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,30 @@ jobs: ] ``` +Use `targets_json` when a project needs to replace the default matrix. Use +`extra_targets_json` to keep every default target and append only the targets +specific to that project: + +```yaml +jobs: + zig: + uses: nullclaw/nullbuilder/.github/workflows/zig-ci.yml@v1 + permissions: + contents: read + with: + binary_name: nullclaw + artifact_prefix: nullclaw + extra_targets_json: >- + [ + {"os":"ubuntu-latest","target":"linux-mipsel-musl","zig_target":"mipsel-linux-musleabi","build_args":"-Dembedded_wasm3=false"} + ] +``` + +`extra_targets_json` is available in the CI, nightly, and release workflows. +Target names must remain unique after the two arrays are merged. An optional +per-target `build_args` string is appended after the workflow-level build +arguments and is useful when one architecture needs a feature override. + ### Nightly ```yaml