From 898560d6750aa4b40cec9201e14c7fab23b2400f Mon Sep 17 00:00:00 2001 From: Max Howell Date: Fri, 2 Feb 2024 14:49:21 -0500 Subject: [PATCH] ci/plan is less wasteful and more legible (#5081) --- .github/scripts/get-ci-matrix.ts | 82 ++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 49 ++++++++----------- 2 files changed, 101 insertions(+), 30 deletions(-) create mode 100755 .github/scripts/get-ci-matrix.ts diff --git a/.github/scripts/get-ci-matrix.ts b/.github/scripts/get-ci-matrix.ts new file mode 100755 index 00000000..ec875df8 --- /dev/null +++ b/.github/scripts/get-ci-matrix.ts @@ -0,0 +1,82 @@ +#!/usr/bin/env -S pkgx deno run -A + +import { hooks, utils } from "pkgx" +import { isString, isArray } from "is-what" + +const rvv: Record[] = [] +for (const arg of Deno.args) { + const pkg = utils.pkg.parse(arg) + const config = await get_config(pkg) + + for (const platform of config.platforms) { + const rv = {} as Record + rv['platform'] = get_matrix(platform) + rv['pkg'] = arg + rvv.push(rv) + } +} + +const ghout = Deno.env.get("GITHUB_OUTPUT") +if (ghout) { + const json = JSON.stringify(rvv) + Deno.writeTextFileSync(ghout, `matrix=${json}`, {append: true}) +} else { + const json = JSON.stringify(rvv, null, 2) + console.log(json) +} + +/////////////////////////////////////////////////////////////////////// + +//TODO should be in libpkgx! +async function get_config(pkg: {project: string}) { + let { platforms, test } = await hooks.usePantry().project(pkg).yaml() + const get_platforms = (() => { + if (!platforms) return ["linux/x86-64", "linux/aarch64", "darwin/x86-64", "darwin/aarch64"] + if (isString(platforms)) platforms = [platforms] + if (!isArray(platforms)) throw new Error(`invalid platform node: ${platforms}`) + const rv = [] + for (const platform of platforms) { + if (platform.match(/^(linux|darwin)\/(aarch64|x86-64)$/)) rv.push(platform) + else if (platform.match(/^(linux|darwin)$/)) rv.push(`${platform}/x86-64`, `${platform}/aarch64`) + else throw new Error(`invalid platform: ${platform}`) + } + return rv + }) + + const qaRequired = test?.["qa-required"] === true + + return { + platforms: get_platforms(), + qaRequired + } +} + +function get_matrix(platform: string) { + const name = platform.replace('/', '+') + switch (platform) { + case 'darwin/aarch64': { + const os = ["self-hosted", "macOS", "ARM64"] + return { + os, name, + tinyname: "²" + }} + case 'darwin/x86-64': { + const os = ["self-hosted", "macOS", "X64"] + return { + os, name, + tinyname: "x64" + }} + case 'linux/x86-64': { + const os = {group: "linux-x86-64"} + return { + os, name, + container: "debian:buster-slim", + tinyname: "*nix64" + }} + case 'linux/aarch64': { + const os = ["self-hosted", "linux", "ARM64"] + return { + os, name, + tinyname: "*nix·ARM64" + }}} +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index befbd59c..f112e465 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,46 +15,39 @@ jobs: plan: runs-on: ubuntu-latest outputs: - pkgs: ${{ steps.diff.outputs.pkgs }} + matrix: ${{ steps.process-diff.outputs.matrix }} steps: - - uses: actions/checkout@v3 + - uses: pkgxdev/setup@v2 + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 id: get-diff with: PATTERNS: projects/**/package.yml - - id: diff + - name: process diff + id: process-diff run: | - for x in ${{ steps.get-diff.outputs.diff }}; do - y=$(echo $x | sed 's#projects/\(.*\)/[^/]*#\1#') - RESULT="$RESULT ${y//$'\n'/}" - done - if [ -n "$RESULT" ]; then - RESULT="$(echo -n $RESULT | jq -R -s -c 'split(" ")')" + if [ -n "${{ steps.get-diff.outputs.diff }}" ]; then + for x in ${{ steps.get-diff.outputs.diff }}; do + y=$(echo $x | sed 's#projects/\(.*\)/[^/]*#\1#') + RESULT="$RESULT ${y//$'\n'/}" + done else - RESULT='["zlib.net"]' + RESULT="zlib.net kernel.org/linux-headers" fi - echo "pkgs=$RESULT" >> $GITHUB_OUTPUT + + ./.github/scripts/get-ci-matrix.ts $RESULT + + - run: echo '${{ steps.process-diff.outputs.matrix }}' | jq build: - if: needs.plan.outputs.pkgs needs: plan - name: ci ${{ matrix.platform.name }} ${{matrix.pkg}} strategy: fail-fast: false matrix: - pkg: ${{ fromJSON(needs.plan.outputs.pkgs) }} - platform: - - os: ["self-hosted", "macOS", "X64"] - name: x64 - - os: ["self-hosted", "macOS", "ARM64"] - name: ² - - os: ["self-hosted", "linux", "ARM64"] - name: "*nix·ARM64" - - os: { group: "linux-x86-64" } - container: debian:buster-slim - name: "*nix64" + include: ${{ fromJSON(needs.plan.outputs.matrix) }} runs-on: ${{ matrix.platform.os }} container: ${{ matrix.platform.container }} + name: ${{ matrix.pkg }} ${{ matrix.platform.tinyname }} env: PKGX_PANTRY_PATH: ${{ github.workspace }} steps: @@ -78,20 +71,16 @@ jobs: - uses: pkgxdev/brewkit/audit@v1 with: pkg: ${{ steps.build.outputs.pkgspec }} - if: steps.build.outputs.pkgspec # prevent tests passing because the build directory is still there + # requires `sudo` because `go` makes unremovable files… - name: wipe builds directory run: | - test -d builds - # requires `sudo` because `go` makes unremovable files... - if command -v sudo; then + if command -v sudo >/dev/null; then SUDO=sudo fi $SUDO rm -rf builds - if: steps.build.outputs.pkgspec - uses: pkgxdev/brewkit/test@v1 with: pkg: ${{ steps.build.outputs.pkgspec }} - if: steps.build.outputs.pkgspec