17 Commits

Author SHA1 Message Date
Dave Rolsky
07f5468cc3 Add release date for v1.0.0
Some checks failed
Lint / Check that code is lint clean using precious (push) Failing after 1m57s
Self-test / Test action (map[cache-cross-binary:false can_execute:true cross-version:19be834 expect_cross:--expect-cross expect_cross_version:19be834 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross 19be834 runs-on:ubuntu-22.04 target… (push) Failing after 1m13s
Self-test / Test action (map[cache-cross-binary:false can_execute:true cross-version:v0.2.3 expect_cross:--expect-cross expect_cross_version:0.2.3 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross v0.2.3 (no cache) runs-on:ubuntu-22.04… (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:false can_execute:true expect_cross:--expect-cross expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 (no cache) runs-on:ubuntu-22.04 target:aarch64-unknown-linux-musl]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross:--expect-cross expect_file_re:x86-64.+FreeBSD expect_stripped: platform_name:FreeBSD-x86_64 runs-on:ubuntu-22.04 target:x86_64-unknown-freebsd]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross:--expect-cross expect_file_re:x86-64.+NetBSD expect_stripped: platform_name:NetBSD-x86_64 runs-on:ubuntu-22.04 target:x86_64-unknown-netbsd]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true cross-version:19be834 expect_cross:--expect-cross expect_cross_version:19be834 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross 19be834 runs-on:ubuntu-22.04 target:… (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true cross-version:v0.2.3 expect_cross:--expect-cross expect_cross_version:0.2.3 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross v0.2.3 runs-on:ubuntu-22.04 target:aarc… (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross: expect_file_re:ELF.+x86-64 expect_stripped:--expect-stripped platform_name:Linux-x86_64 runs-on:ubuntu-22.04 target:x86_64-unknown-linux-musl]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:32.+ARM expect_stripped: platform_name:Linux-arm runs-on:ubuntu-22.04 target:arm-unknown-linux-musleabi]) (push) Failing after 5s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:32.+PowerPC expect_stripped: platform_name:Linux-powerpc runs-on:ubuntu-22.04 target:powerpc-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+PowerPC expect_stripped: platform_name:Linux-powerpc64 runs-on:ubuntu-22.04 target:powerpc64-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+PowerPC expect_stripped: platform_name:Linux-powerpc64le runs-on:ubuntu-22.04 target:powerpc64le-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+RISC-V expect_stripped: platform_name:Linux-riscv64 runs-on:ubuntu-22.04 target:riscv64gc-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+S/390 expect_stripped: platform_name:Linux-s390x runs-on:ubuntu-22.04 target:s390x-unknown-linux-gnu]) (push) Failing after 4s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:ELF.+80386 expect_stripped: platform_name:Linux-i586 runs-on:ubuntu-22.04 target:i586-unknown-linux-musl]) (push) Failing after 4s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:ELF.+80386 expect_stripped: platform_name:Linux-i686 runs-on:ubuntu-22.04 target:i686-unknown-linux-musl]) (push) Failing after 5s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 runs-on:ubuntu-22.04 target:aarch64-unknown-linux-musl]) (push) Failing after 4s
Self-test / Test validate-inputs (push) Successful in 4s
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross: expect_file_re:Aarch64.+Windows expect_stripped: platform_name:Windows-aarch64 runs-on:windows-latest target:aarch64-pc-windows-msvc]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross: expect_file_re:Mach-O.+arm64 expect_stripped:--expect-stripped platform_name:macOS-aarch64 runs-on:macOS-latest target:aarch64-apple-darwin]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross: expect_file_re:80386.+Windows expect_stripped:--expect-stripped platform_name:Windows-i686 runs-on:windows-latest target:i686-pc-windows-msvc]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross: expect_file_re:Mach-O.+x86_64 expect_stripped:--expect-stripped platform_name:macOS-x86_64 runs-on:macOS-latest target:x86_64-apple-darwin]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_file_re:x86-64.+Windows expect_stripped:--expect-stripped platform_name:Windows-x86_64 runs-on:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
2025-01-11 11:57:27 -06:00
Dave Rolsky
1024265def Update Changes.md for caching changes since 1.0.0-beta1 2024-12-24 12:00:59 -06:00
Dave Rolsky
faf2f9fd0a Include the hash of the cross binary in the cache key
This protects against changes to the Docker images that `cross` uses.
2024-12-24 11:39:17 -06:00
Dave Rolsky
a183497a0a Include OS version in cache key when using cargo for builds
If we're running cargo, we need to add the runner name to the cache. Otherwise things that link
against system packages, like openssl, can break when we use the same cache across different
versions of the runner OS. For example, when going from Ubuntu 20.04 to 22.04, we move from OpenSSL
1.1.x to 3.x.
2024-12-24 11:22:45 -06:00
Dave Rolsky
718071590b Don't try to install musl-tools if it's already installed 2024-12-22 15:17:51 -06:00
Dave Rolsky
a1777f5838 Add first step to print all inputs 2024-12-22 15:05:18 -06:00
Dave Rolsky
b1824d4802 Update README.md for version 1 bump
Some checks failed
Lint / Check that code is lint clean using precious (push) Failing after 13s
Self-test / Test action (map[cache-cross-binary:false can_execute:true cross-version:19be834 expect_cross:--expect-cross expect_cross_version:19be834 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross 19be834 runs-on:ubuntu-22.04 target… (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:false can_execute:true cross-version:v0.2.3 expect_cross:--expect-cross expect_cross_version:0.2.3 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross v0.2.3 (no cache) runs-on:ubuntu-22.04… (push) Failing after 1s
Self-test / Test action (map[cache-cross-binary:false can_execute:true expect_cross:--expect-cross expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 (no cache) runs-on:ubuntu-22.04 target:aarch64-unknown-linux-musl]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross:--expect-cross expect_file_re:x86-64.+FreeBSD expect_stripped: platform_name:FreeBSD-x86_64 runs-on:ubuntu-22.04 target:x86_64-unknown-freebsd]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross:--expect-cross expect_file_re:x86-64.+NetBSD expect_stripped: platform_name:NetBSD-x86_64 runs-on:ubuntu-22.04 target:x86_64-unknown-netbsd]) (push) Failing after 1s
Self-test / Test action (map[cache-cross-binary:true can_execute:true cross-version:19be834 expect_cross:--expect-cross expect_cross_version:19be834 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross 19be834 runs-on:ubuntu-22.04 target:… (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true cross-version:v0.2.3 expect_cross:--expect-cross expect_cross_version:0.2.3 expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 with cross v0.2.3 runs-on:ubuntu-22.04 target:aarc… (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross: expect_file_re:ELF.+x86-64 expect_stripped:--expect-stripped platform_name:Linux-x86_64 runs-on:ubuntu-22.04 target:x86_64-unknown-linux-musl]) (push) Failing after 1s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:32.+ARM expect_stripped: platform_name:Linux-arm runs-on:ubuntu-22.04 target:arm-unknown-linux-musleabi]) (push) Failing after 4s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:32.+PowerPC expect_stripped: platform_name:Linux-powerpc runs-on:ubuntu-22.04 target:powerpc-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+PowerPC expect_stripped: platform_name:Linux-powerpc64 runs-on:ubuntu-22.04 target:powerpc64-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+PowerPC expect_stripped: platform_name:Linux-powerpc64le runs-on:ubuntu-22.04 target:powerpc64le-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+RISC-V expect_stripped: platform_name:Linux-riscv64 runs-on:ubuntu-22.04 target:riscv64gc-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:64.+S/390 expect_stripped: platform_name:Linux-s390x runs-on:ubuntu-22.04 target:s390x-unknown-linux-gnu]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:ELF.+80386 expect_stripped: platform_name:Linux-i586 runs-on:ubuntu-22.04 target:i586-unknown-linux-musl]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:ELF.+80386 expect_stripped: platform_name:Linux-i686 runs-on:ubuntu-22.04 target:i686-unknown-linux-musl]) (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross:--expect-cross expect_file_re:aarch64 expect_stripped: platform_name:Linux-aarch64 runs-on:ubuntu-22.04 target:aarch64-unknown-linux-musl]) (push) Failing after 0s
Self-test / Test validate-inputs (push) Failing after 0s
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross: expect_file_re:Aarch64.+Windows expect_stripped: platform_name:Windows-aarch64 runs-on:windows-latest target:aarch64-pc-windows-msvc]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:false expect_cross: expect_file_re:Mach-O.+arm64 expect_stripped:--expect-stripped platform_name:macOS-aarch64 runs-on:macOS-latest target:aarch64-apple-darwin]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross: expect_file_re:80386.+Windows expect_stripped:--expect-stripped platform_name:Windows-i686 runs-on:windows-latest target:i686-pc-windows-msvc]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_cross: expect_file_re:Mach-O.+x86_64 expect_stripped:--expect-stripped platform_name:macOS-x86_64 runs-on:macOS-latest target:x86_64-apple-darwin]) (push) Has been cancelled
Self-test / Test action (map[cache-cross-binary:true can_execute:true expect_file_re:x86-64.+Windows expect_stripped:--expect-stripped platform_name:Windows-x86_64 runs-on:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
2024-12-21 22:27:23 -06:00
Dave Rolsky
3d79b24531 Rename os to runs-on in test matrix workflow 2024-12-21 22:17:14 -06:00
Dave Rolsky
9ec7e60cb6 Clarify use cases in README.md 2024-12-21 22:17:14 -06:00
Dave Rolsky
fd3526da5f Fix example in README.md to use checkout@v4 2024-12-21 22:17:14 -06:00
Dave Rolsky
12331c384e Tweak wording in README.md 2024-12-21 22:17:14 -06:00
Dave Rolsky
dbeb1eb6a2 Replace all Perl scripts with Rust 2024-12-21 22:17:14 -06:00
Dave Rolsky
dad7ec15de Validate inputs to this action 2024-12-21 22:17:14 -06:00
Dave Rolsky
02640563b4 Add bench to command docs 2024-12-21 21:50:18 -06:00
Dave Rolsky
3f82d5723e Use Ubuntu 22.04 for test workflow 2024-12-21 21:50:18 -06:00
Dave Rolsky
fe9ef8cc9c Add mise config and use ruff for Python linting/tidying 2024-12-21 21:50:18 -06:00
Dave Rolsky
7ad7c57bed Add support for Swatinem/rust-cache@v2 2024-12-21 21:50:18 -06:00
20 changed files with 1123 additions and 5259 deletions

View File

@@ -11,15 +11,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Git
run: |
git config --global user.email "jdoe@example.com"
git config --global user.name "J. Doe"
- name: Run install-dev-tools.sh
- name: Install mise
run: |
set -e
mkdir $HOME/bin
./dev/bin/install-dev-tools.sh
set -x
curl https://mise.run | sh
mise install
- name: Run precious
run: |
PATH=$PATH:$HOME/bin precious lint -a
mise exec -- precious lint -a

View File

@@ -5,193 +5,193 @@ on:
pull_request:
jobs:
test:
name: Test
test-action:
name: Test action
strategy:
fail-fast: false
matrix:
platform:
- platform_name: FreeBSD-x86_64
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: x86_64-unknown-freebsd
cache-cross-binary: true
expect_file_re: "x86-64.+FreeBSD"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: false
- platform_name: Linux-x86_64
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: x86_64-unknown-linux-musl
cache-cross-binary: true
expect_file_re: "ELF.+x86-64"
expect_cross: "--no-expect-cross"
expect_cross: ""
expect_stripped: "--expect-stripped"
can_execute: true
- platform_name: Linux-aarch64
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: aarch64-unknown-linux-musl
cache-cross-binary: true
expect_file_re: "aarch64"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-aarch64 (no cache)
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: aarch64-unknown-linux-musl
cache-cross-binary: false
expect_file_re: "aarch64"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-aarch64 with cross v0.2.3
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: aarch64-unknown-linux-musl
cross-version: "v0.2.3"
cache-cross-binary: true
expect_file_re: "aarch64"
expect_cross: "--expect-cross"
expect_cross_version: "0.2.3"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-aarch64 with cross v0.2.3 (no cache)
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: aarch64-unknown-linux-musl
cross-version: "v0.2.3"
cache-cross-binary: false
expect_file_re: "aarch64"
expect_cross: "--expect-cross"
expect_cross_version: "0.2.3"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-aarch64 with cross 19be834
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: aarch64-unknown-linux-musl
cross-version: "19be834"
cache-cross-binary: true
expect_file_re: "aarch64"
expect_cross: "--expect-cross"
expect_cross_version: "19be834"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-aarch64 with cross 19be834
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: aarch64-unknown-linux-musl
cross-version: "19be834"
cache-cross-binary: false
expect_file_re: "aarch64"
expect_cross: "--expect-cross"
expect_cross_version: "19be834"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-arm
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: arm-unknown-linux-musleabi
cache-cross-binary: true
expect_file_re: "32.+ARM"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-i586
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: i586-unknown-linux-musl
cache-cross-binary: true
expect_file_re: "ELF.+80386"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-i686
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: i686-unknown-linux-musl
cache-cross-binary: true
expect_file_re: "ELF.+80386"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-powerpc
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: powerpc-unknown-linux-gnu
cache-cross-binary: true
expect_file_re: "32.+PowerPC"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-powerpc64
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: powerpc64-unknown-linux-gnu
cache-cross-binary: true
expect_file_re: "64.+PowerPC"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-powerpc64le
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: powerpc64le-unknown-linux-gnu
cache-cross-binary: true
expect_file_re: "64.+PowerPC"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-riscv64
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: riscv64gc-unknown-linux-gnu
cache-cross-binary: true
expect_file_re: "64.+RISC-V"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: Linux-s390x
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: s390x-unknown-linux-gnu
cache-cross-binary: true
expect_file_re: "64.+S/390"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: true
- platform_name: NetBSD-x86_64
os: ubuntu-20.04
runs-on: ubuntu-22.04
target: x86_64-unknown-netbsd
cache-cross-binary: true
expect_file_re: "x86-64.+NetBSD"
expect_cross: "--expect-cross"
expect_stripped: "--no-expect-stripped"
expect_stripped: ""
can_execute: false
- platform_name: Windows-aarch64
os: windows-latest
runs-on: windows-latest
target: aarch64-pc-windows-msvc
cache-cross-binary: true
expect_file_re: "Aarch64.+Windows"
expect_cross: "--no-expect-cross"
expect_stripped: "--no-expect-stripped"
expect_cross: ""
expect_stripped: ""
can_execute: false
- platform_name: Windows-i686
os: windows-latest
runs-on: windows-latest
target: i686-pc-windows-msvc
cache-cross-binary: true
expect_file_re: "80386.+Windows"
expect_cross: "--no-expect-cross"
expect_cross: ""
expect_stripped: "--expect-stripped"
can_execute: true
- platform_name: Windows-x86_64
os: windows-latest
runs-on: windows-latest
target: x86_64-pc-windows-msvc
cache-cross-binary: true
expect_file_re: "x86-64.+Windows"
@@ -199,24 +199,24 @@ jobs:
can_execute: true
- platform_name: macOS-x86_64
os: macOS-latest
runs-on: macOS-latest
target: x86_64-apple-darwin
cache-cross-binary: true
expect_file_re: "Mach-O.+x86_64"
expect_cross: "--no-expect-cross"
expect_cross: ""
expect_stripped: "--expect-stripped"
can_execute: true
- platform_name: macOS-aarch64
os: macOS-latest
runs-on: macOS-latest
target: aarch64-apple-darwin
cache-cross-binary: true
expect_file_re: "Mach-O.+arm64"
expect_cross: "--no-expect-cross"
expect_cross: ""
expect_stripped: "--expect-stripped"
can_execute: false
runs-on: ${{ matrix.platform.os }}
runs-on: ${{ matrix.platform.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -285,9 +285,22 @@ jobs:
- name: Check binary and cross on ${{ matrix.platform.platform_name }}
shell: bash
run: |
tests/check-binary.pl \
set -e
set -x
cargo run --manifest-path ./run-tests/Cargo.toml -- \
--checkout-root "$PWD" \
--target "${{ matrix.platform.target }}" \
--expect-file-re "${{ matrix.platform.expect_file_re }}" \
--expect-cross-version "${{ matrix.platform.expect_cross_version }}" \
${{ matrix.platform.expect_cross }} \
${{ matrix.platform.expect_stripped }}
test-validate-inputs:
name: Test validate-inputs
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run tests
shell: bash
run: ./validate-inputs.py --test

1
.gitignore vendored
View File

@@ -3,4 +3,5 @@
/package.json
.\#*
\#*\#
run-tests/**/target/**
test-project/**/target/**

View File

@@ -1,3 +1,34 @@
## 1.0.0 - 2025-01-11
The addition of caching is a significant behavior change for this action, so the version has been
bumped to v1.0.0 because of this change.
- This action will now configure and use `Swatinem/rust-cache` by default for you. It will include
the `target` parameter as part of the cache key automatically, as well as the OS version when
using `cargo` on Linux. Suggested by @jennydaman (Jennings Zhang). GH #23.
- This action now validates its input and will exit early if they are not valid. GH #35.
- When compiling for `musl` targets, this action will not try to reinstall the `musl-tools` package
if it's already installed.
The following changes were made since the 1.0.0-beta1 release:
- The cache key includes information that causes the cache to not be re-used when the system running
`cargo` or `cross` changes. When using `cargo` on Linux, this is the OS version, like "Ubuntu
22.04". When using `cross`, this is the hash of the `cross` binary itself. This is needed because
the Docker images that `cross` uses can change when the binary is updated. This can include
changing the underlying Docker image base OS, in which case it's quite likely the old cache
contents would be incompatible with the the new image.
## 1.0.0-beta1 - 2024-12-21
The addition of caching is a significant behavior change for this action, so the version has been
bumped to v1.0.0 because of this change.
- This action will now configure and use `Swatinem/rust-cache` by default for you. It will include
the `target` parameter as part of the cache key automatically. Suggested by @jennydaman (Jennings
Zhang). GH #23.
- This action now validates its input and will exit early if they are not valid. GH #35.
## 0.0.17 - 2024-11-23
- Added support for running `cargo bench` or `cross bench`. Implemented by @RaulTrombin (Raul Victor

View File

@@ -43,9 +43,9 @@ jobs:
runs-on: ${{ matrix.platform.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Build binary
uses: houseabsolute/actions-rust-cross@v0
uses: houseabsolute/actions-rust-cross@v1
with:
command: ${{ matrix.platform.command }}
target: ${{ matrix.platform.target }}
@@ -58,25 +58,30 @@ jobs:
target: ${{ matrix.platform.target }}
```
Note that for Linux or BSD targets, you should always set the `runs-on` key to an x86-64
architecture runner. If you want to do native ARM compilation, for example using
`ubuntu-latest-arm`, then there's no point in using this action. This action is only tested on
Note that for Linux or BSD targets, you should always set the `runs-on` key to a Linux x86-64
architecture runner.
If you _only_ want to do native ARM compilation, for example using the `ubuntu-latest-arm` runner,
then there's no need to use this action. However, if you want to compile for _many_ platforms,
including Linux ARM, using this action will simplify your config. This action is only tested on
Ubuntu x86-64, Windows, and macOS runners.
## Input Parameters
This action takes the following parameters:
| Key | Type | Required? | Description |
| ------------------- | ---------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `command` | string (one of `build`, `test`, or `both`) | no | The command(s) to run. The default is `build`. Running the `test` command will fail with \*BSD targets and non-x86 Windows. |
| `target` | string | yes | The target triple to compile for. This should be one of the targets found by running `rustup target list`. |
| `working-directory` | string | no | The working directory in which to run the `cargo` or `cross` commands. Defaults to the current directory (`.`). |
| `toolchain` | string (one of `stable`, `beta`, or `nightly`) | no | The Rust toolchain version to install. The default is `stable`. |
| `GITHUB_TOKEN` | string | no | Defaults to the value of `${{ github.token }}`. |
| `args` | string | no | A string-separated list of arguments to be passed to `cross build`, like `--release --locked`. |
| `strip` | boolean (`true` or `false`) | no | If this is true, then the resulting binaries will be stripped if possible. This is only possible for binaries which weren't cross-compiled. |
| `cross-version` | string | no | This can be used to set the version of `cross` to use. If specified, it should be a specific `cross` release tag (like `v0.2.3`) or a git ref (commit hash, `HEAD`, etc.). If this is not set then the latest released version will always be used. If this is set to a git ref then the version corresponding to that ref will be installed. |
| Key | Type | Required? | Description |
| ----------------------- | -------------------------------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `command` | string (one of `build`, `test`, `both` (build and test), or `bench`) | no | The command(s) to run. The default is `build`. Running the `test` command will fail with \*BSD targets and non-x86 Windows. |
| `target` | string | yes | The target triple to compile for. This should be one of the targets found by running `rustup target list`. |
| `working-directory` | string | no | The working directory in which to run the `cargo` or `cross` commands. Defaults to the current directory (`.`). |
| `toolchain` | string (one of `stable`, `beta`, or `nightly`) | no | The Rust toolchain version to install. The default is `stable`. |
| `GITHUB_TOKEN` | string | no | Defaults to the value of `${{ github.token }}`. |
| `args` | string | no | A string-separated list of arguments to be passed to `cross build`, like `--release --locked`. |
| `strip` | boolean (`true` or `false`) | no | If this is true, then the resulting binaries will be stripped if possible. This is only possible for binaries which weren't cross-compiled. |
| `cross-version` | string | no | This can be used to set the version of `cross` to use. If specified, it should be a specific `cross` release tag (like `v0.2.3`) or a git ref (commit hash, `HEAD`, etc.). If this is not set then the latest released version will always be used. If this is set to a git ref then the version corresponding to that ref will be installed. |
| `use-rust-cache` | boolean | no | Whether or not to use [the `Swatinem/rust-cache@v2` action](https://github.com/Swatinem/rust-cache). This defaults to true. |
| `rust-cache-parameters` | string (containing JSON) | no | This must be a string containing valid JSON. The JSON should be an object where the keys are the parameters for [the `Swatinem/rust-cache@v2` action](https://github.com/Swatinem/rust-cache). |
## How it Works
@@ -94,12 +99,22 @@ build `cross`.
When compiling on Windows, it will do so in a Powershell environment, which can matter in some
corner cases, like compiling the `openssl` crate with the `vendored` feature.
Finally, it will run `strip` to strip the binaries if the `strip` parameter is true. This is only
possible for builds that are not done via `cross`. In addition, Windows builds for `aarch64` cannot
be stripped either.
By default, it will use
[the `Swatinem/rust-cache@v2` action](https://github.com/Swatinem/rust-cache) to cache compiled
dependencies for this crate. Note that per the documentation for this action, it has fairly limited
value for crates without a `Cargo.lock` file. The `key` parameter passed to this action will always
include the value of the `target` input. If you specify a `key` parameter in
`rust-cache-parameters`, then the `target` input will be appended to the value you specify.
## Caching Rust Compilation Output
When running `cargo` on a Linux system, it will also include the output of running
`lsb_release --short --description` in the cache key. This is important for crates that link against
system libraries. If those library versions change across OS versions (e.g. Ubuntu 20.04 to 22.04),
then the cache will be broken for these cases.
You can use the [Swatinem/rust-cache](https://github.com/Swatinem/rust-cache) action with this one
seamlessly, whether or not a specific build target needs `cross`. There is no special configuration
that you need for this. It just works.
When running `cross`, the hash of the `cross` binary will be included in the cache key. This is done
because the Docker images that `cross` uses can change when `cross` is updated. We want to make sure
that we do not re-use the cache across changes when these images change.
Finally, it will run `strip` to strip the binaries it builds if the `strip` parameter is true. This
is only possible for builds that are not done via `cross`. In addition, Windows builds for `aarch64`
cannot be stripped either.

View File

@@ -6,20 +6,20 @@ branding:
description: |
Cross compile your Rust projects with cross (https://github.com/cross-rs/cross).
inputs:
working-directory:
description: The working directory for each step
default: "."
target:
description: The target platform
required: true
command:
description: |
The commands to run. This must be one of "build", "test", "both" (build and test), or "bench".
default: build
target:
description: The target platform
required: true
toolchain:
description: |
The target toolchain to use (one of "stable", "beta", or "nightly").
default: stable
working-directory:
description: The working directory for each step
default: "."
GITHUB_TOKEN:
description: |
A GitHub token, available in the secrets.GITHUB_TOKEN working-directory variable.
@@ -41,12 +41,38 @@ inputs:
Cache the cross binary if one is installed. This is primarily for use in
tests of this action.
default: true
use-rust-cache:
description: |
Use `Swatinem/rust-cache@v2`. Defaults to true.
default: true
rust-cache-parameters:
description: |
A JSON string containing parameters to pass to `Swatinem/rust-cache@v2`. You can use the
`toJSON()` function in your action to make passing this easier.
default: "{}"
runs:
using: composite
steps:
- name: Show inputs
shell: bash
run: |
echo '${{ toJSON(inputs) }}'
- name: Add this action's path to PATH
shell: bash
run: echo "${{ github.action_path }}" >> $GITHUB_PATH
- name: Validate inputs
shell: bash
run: |
"${{ github.action_path }}"/validate-inputs.py "${{ github.workspace }}"
env:
INPUTS_target: ${{ inputs.target }}
INPUTS_command: ${{ inputs.command }}
INPUTS_toolchain: ${{ inputs.toolchain }}
INPUTS_working_directory: ${{ inputs.working-directory }}
INPUTS_strip: ${{ inputs.strip }}
INPUTS_cache_cross_binary: ${{ inputs.cache-cross-binary }}
INPUTS_use_rust_cache: ${{ inputs.use-rust-cache }}
INPUTS_rust_cache_parameters: ${{ inputs.rust-cache-parameters }}
- name: Determine whether we need to cross-compile
id: determine-cross-compile
shell: bash
@@ -85,7 +111,12 @@ runs:
GITHUB_TOKEN: ${{ inputs.GITHUB_TOKEN }}
- name: Install musl-tools on Linux if target includes "musl"
shell: bash
run: sudo apt-get update --yes && sudo apt-get install --yes musl-tools
run: |
if dpkg -l musl-tools | grep -q "^ii\s*musl-tools"; then
exit 0
fi
sudo apt-get update --yes && \
sudo apt-get install --yes musl-tools
if: steps.determine-cross-compile.outputs.needs-cross != 'true' && contains(inputs.target, 'musl')
- name: Set build command
id: set-build-command
@@ -95,6 +126,28 @@ runs:
id: determine-cargo-commands
shell: bash
run: determine-cargo-commands.sh ${{ inputs.command }}
- name: Parse `rust-cache-parameters` and set inputs for `Swatinem/rust-cache@v2`
id: parse-rust-cache-parameters
shell: bash
run: |
set -e
set -x
set -o pipefail
OS_VERSION=""
if [ -x /usr/bin/lsb_release ]; then
# This will be something like "Ubuntu 22.04.5 LTS"
OS_VERSION="$( lsb_release --short --description )"
fi
# This will get the inputs JSON from the `RUST_CACHE_PARAMETERS` env var. This avoids
# any string interpolation issues, since the inputs will contain quotes.
parse-and-set-rust-cache-parameters.py "${{ inputs.target }}" "${{ steps.set-build-command.outputs.build-command }}" "$OS_VERSION"
env:
RUST_CACHE_PARAMETERS: ${{ inputs.rust-cache-parameters }}
if: inputs.use-rust-cache == 'true'
- name: Cache cargo & target directories
uses: Swatinem/rust-cache@v2
with: ${{ steps.parse-rust-cache-parameters.outputs }}
if: inputs.use-rust-cache == 'true'
- name: Run tests (*nix)
working-directory: ${{ inputs.working-directory }}
shell: bash

View File

@@ -1,51 +0,0 @@
#!/bin/bash
set -eo pipefail
set -x
function run() {
echo "$1"
eval "$1"
}
function install_tools() {
curl --silent --location \
https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh |
sh
run "ubi --project houseabsolute/precious --in $HOME/bin"
run "ubi --project houseabsolute/omegasort --in $HOME/bin"
run "ubi --project koalaman/shellcheck --in $HOME/bin"
run "ubi --project mvdan/sh --in $HOME/bin --exe shfmt"
run "ubi --project crate-ci/typos --in $HOME/bin"
run "npm install prettier"
run "curl -L https://cpanmin.us/ -o $HOME/bin/cpanm"
run "chmod 0755 $HOME/bin/cpanm"
run "$HOME/bin/cpanm --sudo --notest Perl::Tidy"
}
if [ "$1" == "-v" ]; then
set -x
fi
mkdir -p "$HOME"/bin
set +e
echo ":$PATH:" | grep --extended-regexp ":$HOME/bin:" >&/dev/null
# shellcheck disable=SC2181
if [ "$?" -eq "0" ]; then
path_has_home_bin=1
fi
set -e
if [ -z "$path_has_home_bin" ]; then
PATH=$HOME/bin:$PATH
fi
install_tools
echo "Tools were installed into $HOME/bin."
if [ -z "$path_has_home_bin" ]; then
echo "You should add $HOME/bin to your PATH."
fi
exit 0

52
git/setup.py Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env python3
# This code was mostly written by Claude.ai.
import os
import sys
def main() -> None:
"""
Main entry point to create a pre-commit hook symlink.
"""
symlink_hook("pre-commit")
def symlink_hook(hook: str) -> None:
"""
Create a symlink for a Git hook if it doesn't already exist.
Args:
hook: Name of the Git hook (e.g., 'pre-commit')
"""
# Path to the hook in .git/hooks
dot_hook_path = os.path.join(".git", "hooks", hook)
# Path to the actual hook script
file_hook_path = os.path.join("git", "hooks", f"{hook}.sh")
# Relative symlink path
link_path = os.path.join("..", "..", file_hook_path)
# Check if the hook already exists
if os.path.exists(dot_hook_path):
# If it's already a symlink, check if it points to the correct location
if os.path.islink(dot_hook_path):
# If the existing symlink is correct, do nothing
if os.readlink(dot_hook_path) == link_path:
return
# If a hook exists and is not the expected symlink, warn and exit
print(f"You already have a hook at {dot_hook_path}!", file=sys.stderr)
return
# Create the symlink
try:
os.symlink(link_path, dot_hook_path)
except OSError as e:
print(f"Error creating symlink: {e}", file=sys.stderr)
if __name__ == "__main__":
main()

10
mise.toml Normal file
View File

@@ -0,0 +1,10 @@
[tools]
node = "22.11.0"
"npm:prettier" = "3.4.1"
ruff = "0.8.3"
shellcheck = "v0.10.0"
shfmt = "v3.10.0"
taplo = "0.9.3"
typos = "1.28.1"
"ubi:houseabsolute/omegasort" = "v0.1.3"
"ubi:houseabsolute/precious" = "v0.7.3"

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env python3
import json
import os
import sys
import hashlib
def main():
target = sys.argv[1]
build_command = sys.argv[2]
os_version = sys.argv[3]
parameters = json.loads(os.environ["RUST_CACHE_PARAMETERS"])
if "key" not in parameters:
parameters["key"] = target
else:
parameters["key"] += "-{}".format(target)
if build_command == "cargo":
# If we're running cargo, we need to add the OS version to the cache. Otherwise things that link
# against system packages, like openssl, can break when we use the same cache across different
# versions of the runner OS. For example, when going from Ubuntu 20.04 to 22.04, we move from
# OpenSSL 1.1.x to 3.x.
parameters["key"] += "-{}".format(os_version)
else:
# Otherwise we want to include the `cross` binary's hash. The Docker images that `cross`
# uses can change when the binary is updated. This protects us from using the same cache
# inside containers that have changed.
parameters["key"] += "-cross-binary-hash-{}".format(
get_file_hash(build_command)
)
file = os.environ["GITHUB_OUTPUT"]
with open(file, "w") as f:
for key, value in parameters.items():
f.write(f"{key}={value}")
def get_file_hash(build_command):
with open(build_command, "rb") as f:
file_hash = hashlib.sha256()
while chunk := f.read(65536):
file_hash.update(chunk)
return file_hash.hexdigest()
main()

View File

@@ -3,6 +3,80 @@ exclude = [
"tests/lib/**/*",
]
[commands.clippy]
type = "lint"
include = "**/*.rs"
invoke = "once"
path-args = "none"
working-dir.chdir-to = "run-tests"
cmd = [
"cargo",
"clippy",
"--color",
"always",
"--locked",
"--all-targets",
"--all-features",
"--",
"-D",
"clippy::pedantic",
]
ok_exit_codes = 0
lint_failure_exit_codes = 101
expect_stderr = true
labels = ["default"]
[commands."clippy --fix"]
type = "tidy"
include = "**/*.rs"
invoke = "once"
path-args = "none"
working-dir.chdir-to = "run-tests"
cmd = [
"cargo",
"clippy",
"--fix",
"--allow-dirty",
"--locked",
"--all-targets",
"--all-features",
"--",
"-D",
"clippy::pedantic",
]
ok_exit_codes = 0
lint_failure_exit_codes = 101
expect_stderr = true
labels = ["default"]
[commands.rustfmt]
type = "both"
include = "**/*.rs"
working-dir.chdir-to = "run-tests"
cmd = ["rustfmt", "--edition", "2021"]
lint_flags = "--check"
ok_exit_codes = [0]
lint_failure_exit_codes = [1]
labels = ["default", "fast-tidy"]
[commands."ruff for linting"]
type = "both"
include = [ "**/*.py" ]
cmd = "ruff"
lint_flags = [ "check" ]
tidy_flags = [ "check", "--fix" ]
ok_exit_codes = 0
lint_failure_exit_codes = 1
[commands."ruff for tidying"]
type = "both"
include = [ "**/*.py" ]
cmd = "ruff"
lint_flags = [ "format", "--check" ]
tidy_flags = [ "format" ]
ok_exit_codes = 0
lint_failure_exit_codes = 1
[commands.typos]
type = "both"
include = "**/*"
@@ -13,21 +87,10 @@ tidy_flags = "--write-changes"
ok-exit-codes = 0
lint-failure-exit-codes = 2
[commands.perltidy]
type = "both"
include = [ "**/*.{pl,pm,t,psgi}" ]
exclude = "tests/lib/**"
cmd = [ "perltidy", "--profile=$PRECIOUS_ROOT/perltidyrc" ]
lint_flags = [ "--assert-tidy", "--no-standard-output", "--outfile=/dev/null" ]
tidy_flags = [ "--backup-and-modify-in-place", "--backup-file-extension=/" ]
ok_exit_codes = 0
lint_failure_exit_codes = 2
ignore_stderr = "Begin Error Output Stream"
[commands.prettier-md]
type = "both"
include = [ "**/*.md" ]
cmd = [ "./node_modules/.bin/prettier", "--no-config", "--print-width", "100", "--prose-wrap", "always" ]
cmd = [ "prettier", "--no-config", "--print-width", "100", "--prose-wrap", "always" ]
lint_flags = "--check"
tidy_flags = "--write"
ok_exit_codes = 0
@@ -37,7 +100,7 @@ ignore_stderr = [ "Code style issues" ]
[commands.prettier-yml]
type = "both"
include = [ "**/*.yml" ]
cmd = [ "./node_modules/.bin/prettier", "--no-config" ]
cmd = [ "prettier", "--no-config" ]
lint_flags = "--check"
tidy_flags = "--write"
ok_exit_codes = 0

314
run-tests/Cargo.lock generated Normal file
View File

@@ -0,0 +1,314 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "clap"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "is_executable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a1b5bad6f9072935961dfbf1cced2f3d129963d091b6f69f007fe04e758ae2"
dependencies = [
"winapi",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "run-tests"
version = "0.1.0"
dependencies = [
"clap",
"is_executable",
"regex",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

9
run-tests/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "run-tests"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.5.23", features = ["derive"] }
is_executable = "1.0.4"
regex = "1.11.1"

155
run-tests/src/main.rs Normal file
View File

@@ -0,0 +1,155 @@
// Mostly written by Claude.ai.
use clap::Parser;
use is_executable::is_executable;
use regex::Regex;
use std::{
env,
path::{Path, PathBuf},
process::Command,
};
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(long)]
checkout_root: String,
#[arg(long)]
target: String,
#[arg(long)]
expect_file_re: Option<String>,
#[arg(long)]
expect_cross: bool,
#[arg(long)]
expect_cross_version: Option<String>,
#[arg(long)]
expect_stripped: bool,
}
fn main() {
let args = Args::parse();
let runner_temp = env::var("RUNNER_TEMP").expect("RUNNER_TEMP is not set");
let runner_temp_path = PathBuf::from(runner_temp);
check_cross(
&runner_temp_path,
args.expect_cross,
args.expect_cross_version.as_deref(),
);
let checkout_root_path = PathBuf::from(args.checkout_root);
let bin_paths = vec![
checkout_root_path
.join("target")
.join(&args.target)
.join("debug")
.join("bin1"),
checkout_root_path
.join("target")
.join(&args.target)
.join("debug")
.join("bin2"),
checkout_root_path
.join("subcrate")
.join("target")
.join(&args.target)
.join("debug")
.join("subcrate"),
];
for mut bin_path in bin_paths {
if cfg!(windows) {
bin_path.set_extension("exe");
}
check_binary(
&bin_path,
args.expect_file_re.as_deref(),
args.expect_stripped,
);
}
}
fn check_cross(bin_dir: &Path, expect_cross: bool, expect_cross_version: Option<&str>) {
let cross_path = bin_dir.join("cross");
if expect_cross {
assert!(cross_path.is_file(), "`cross` exists");
if let Some(expected_version) = expect_cross_version {
let output = Command::new(&cross_path)
.arg("--version")
.output()
.expect("Failed to execute `cross` command");
let version = String::from_utf8(output.stdout)
.expect("`cross --version` stdout was not valid UTF-8");
assert!(
version.contains(expected_version),
"`cross` version matches expected version"
);
}
} else {
assert!(!cross_path.exists(), "`cross` was not downloaded");
}
}
fn check_binary(bin_path: &PathBuf, expect_file_re: Option<&str>, expect_stripped: bool) {
assert!(bin_path.exists(), "Binary at {} exists", bin_path.display());
assert!(
bin_path.is_file(),
"Binary at {} is a file",
bin_path.display()
);
assert!(
is_executable(bin_path),
"Binary at {} is executable",
bin_path.display()
);
let output = Command::new("file")
.arg("--brief")
.arg(bin_path)
.output()
.expect("Failed to execute `file` command");
let file_output = String::from_utf8_lossy(&output.stdout);
if let Some(file_re) = expect_file_re {
let re = Regex::new(file_re).expect("Invalid regex");
assert!(
re.is_match(&file_output),
"`file` output for {} matches expected output",
bin_path.display(),
);
}
// `file` on macOS doesn't report if the binary is stripped.
if cfg!(target_os = "macos") {
return;
}
if expect_stripped {
assert!(
!file_output.contains("not stripped"),
"`file` does not report {} as not stripped",
bin_path.display(),
);
assert!(
file_output.contains("stripped"),
"`file` reports {} as stripped",
bin_path.display(),
);
} else if cfg!(windows) {
assert!(
!file_output.contains("stripped"),
"`file` does not report {} as stripped",
bin_path.display(),
);
} else {
assert!(
file_output.contains("not stripped"),
"`file` reports {} as not stripped",
bin_path.display(),
);
}
}

View File

@@ -4,7 +4,7 @@ fn fibonacci(n: u64) -> u64 {
match n {
0 => 1,
1 => 1,
n => fibonacci(n-1) + fibonacci(n-2),
n => fibonacci(n - 1) + fibonacci(n - 2),
}
}

View File

@@ -0,0 +1 @@

View File

@@ -1,114 +0,0 @@
#!/usr/bin/env perl
use v5.30;
use strict;
use warnings;
no warnings 'experimental::signatures';
use feature 'signatures';
use autodie;
use FindBin qw( $Bin );
use File::Spec;
use lib File::Spec->catdir( $Bin, 'lib' );
use Getopt::Long;
use IPC::System::Simple qw( capturex );
use Path::Tiny qw( path );
use Test::More;
sub main {
my $target;
my $expect_cross;
my $expect_cross_version;
my $expect_file_re;
my $expect_stripped;
GetOptions(
'target=s' => \$target,
'expect-file-re=s' => \$expect_file_re,
'expect-cross!' => \$expect_cross,
'expect-cross-version=s' => \$expect_cross_version,
'expect-stripped!' => \$expect_stripped,
);
check_cross(
path( $ENV{RUNNER_TEMP} ),
$expect_cross,
$expect_cross_version
);
for my $bin (
path( qw( . target ), $target, qw( debug bin1 ) ),
path( qw( . target ), $target, qw( debug bin2 ) ),
path( qw( . subcrate target ), $target, qw( debug subcrate ) )
) {
check_binary( $bin, $expect_file_re, $expect_stripped );
}
done_testing();
}
sub check_cross ( $bin_dir, $expect_cross, $expect_cross_version ) {
my $cross = $bin_dir->child('cross');
if ($expect_cross) {
ok( $cross->is_file && -x $cross, 'found `cross` in $PATH' );
if ($expect_cross_version) {
my $version = capturex( $cross, '--version' );
like(
$version, qr/\Q$expect_cross_version/,
'cross version matches expected version'
);
}
}
else {
ok( !$cross->exists, 'did not find `cross` in $PATH' );
}
}
sub check_binary ( $bin, $expect_file_re, $expect_stripped ) {
ok( $bin->exists, "Binary at $bin exists" )
or return;
ok( $bin->is_file, "Binary at $bin is a file" )
or return;
ok( -x $bin, "Binary at $bin is executable" )
or return;
my $file = capturex( qw( file --brief ), $bin ) // q{};
chomp $file;
like(
$file, qr/$expect_file_re/,
"`file` output for $bin matches expected output"
);
# The file command on macOS doesn't report whether the binary is stripped
# or not.
return if $^O eq 'darwin';
if ($expect_stripped) {
unlike(
$file, qr/not stripped/,
"`file` does not report $bin as not stripped"
);
like( $file, qr/stripped/, "`file` reports $bin as stripped" );
}
else {
if ( $^O eq 'MSWin32' || $^O eq 'msys' ) {
# On Windows, unstripped binaries don't contain the word
# "stripped" at all.
unlike(
$file, qr/stripped/,
"`file` does not report $bin as stripped"
);
}
else {
like(
$file, qr/not stripped/,
"`file` reports $bin as not stripped"
);
}
}
}
main();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

261
validate-inputs.py Executable file
View File

@@ -0,0 +1,261 @@
#!/usr/bin/env python3
# Written by Claude.ai
import os
import json
from pathlib import Path
from typing import Dict, List, Union
import tempfile
import unittest
class InputValidator:
"""Validate inputs for a GitHub Action."""
def __init__(self, repo_root: Union[str, Path]):
"""
Create a new InputValidator by collecting environment variables.
Args:
repo_root: Path to the repository root
"""
self.repo_root = Path(repo_root)
self.inputs: Dict[str, str] = {
key.replace("INPUTS_", "").lower(): value
for key, value in os.environ.items()
if key.startswith("INPUTS_")
}
def validate(self) -> List[str]:
"""
Validate all inputs according to specifications.
Returns:
List of validation errors. Empty list means all inputs are valid.
"""
validation_errors: List[str] = []
# Check for required 'target' parameter
if "target" not in self.inputs:
validation_errors.append("'target' is a required parameter")
# Validate command if present
if "command" in self.inputs:
valid_commands = {"build", "test", "both", "bench"}
if self.inputs["command"] not in valid_commands:
validation_errors.append(
f"Invalid 'command'. Must be one of {sorted(valid_commands)}"
)
# Validate toolchain if present
if "toolchain" in self.inputs:
valid_toolchains = {"stable", "beta", "nightly"}
if self.inputs["toolchain"] not in valid_toolchains:
validation_errors.append(
f"Invalid 'toolchain'. Must be one of {sorted(valid_toolchains)}"
)
# Validate working directory if present
if "working_directory" in self.inputs:
path = Path(self.inputs["working_directory"])
if not path.is_absolute():
path = self.repo_root / path
if not path.exists():
validation_errors.append(
f"'working-directory' does not exist: {self.inputs['working_directory']}"
)
elif not path.is_dir():
validation_errors.append(
f"'working-directory' is not a directory: {self.inputs['working_directory']}"
)
# Validate boolean flags
boolean_flags = {"cache_cross_binary", "strip", "use_rust_cache"}
for flag in boolean_flags:
if flag in self.inputs and self.inputs[flag] not in {"true", "false"}:
validation_errors.append(f"'{flag}' must be either 'true' or 'false'")
# Validate rust-cache-parameters JSON if present
if "rust_cache_parameters" in self.inputs:
try:
json.loads(self.inputs["rust_cache_parameters"])
except json.JSONDecodeError:
validation_errors.append("'rust-cache-parameters' must be valid JSON")
return validation_errors
def main() -> None:
"""Main function for running the validator."""
import sys
validator = InputValidator(sys.argv[1])
errors = validator.validate()
if not errors:
print("All inputs are valid.")
sys.exit(0)
else:
for error in errors:
print(error, file=sys.stderr)
sys.exit(1)
class TestInputValidator(unittest.TestCase):
"""Unit tests for the InputValidator."""
def setUp(self) -> None:
"""Set up test environment."""
# Clear existing INPUTS_ environment variables
for key in list(os.environ.keys()):
if key.startswith("INPUTS_"):
del os.environ[key]
def setup_env(self, inputs: Dict[str, str]) -> None:
"""Helper function to set up environment variables for testing."""
for key, value in inputs.items():
env_key = f"INPUTS_{key.upper().replace('-', '_')}"
os.environ[env_key] = value
def test_get_inputs_from_env(self) -> None:
"""Test getting inputs from environment variables."""
inputs = {
"target": "x86_64-unknown-linux-gnu",
"command": "build",
"toolchain": "stable",
"use-rust-cache": "true",
}
self.setup_env(inputs)
validator = InputValidator("/root")
for key, value in validator.inputs.items():
self.assertEqual(value, inputs[key.replace("_", "-")])
def test_validate_missing_target(self) -> None:
"""Test validation with missing target."""
self.setup_env({})
validator = InputValidator("/root")
errors = validator.validate()
self.assertTrue(errors)
def test_validate_valid_command(self) -> None:
"""Test validation of valid commands."""
valid_commands = ["build", "test", "both", "bench"]
for command in valid_commands:
self.setup_env({"target": "x86_64-unknown-linux-gnu", "command": command})
validator = InputValidator("/root")
errors = validator.validate()
self.assertFalse(errors, f"Command '{command}' should be valid")
def test_validate_invalid_command(self) -> None:
"""Test validation of invalid command."""
self.setup_env({"target": "x86_64-unknown-linux-gnu", "command": "invalid"})
validator = InputValidator("/root")
errors = validator.validate()
self.assertTrue(errors)
def test_validate_valid_toolchain(self) -> None:
"""Test validation of valid toolchains."""
valid_toolchains = ["stable", "beta", "nightly"]
for toolchain in valid_toolchains:
self.setup_env(
{"target": "x86_64-unknown-linux-gnu", "toolchain": toolchain}
)
validator = InputValidator("/root")
errors = validator.validate()
self.assertFalse(errors, f"Toolchain '{toolchain}' should be valid")
def test_validate_invalid_toolchain(self) -> None:
"""Test validation of invalid toolchain."""
self.setup_env({"target": "x86_64-unknown-linux-gnu", "toolchain": "unknown"})
validator = InputValidator("/root")
errors = validator.validate()
self.assertTrue(errors)
def test_validate_working_directory(self) -> None:
"""Test validation of working directory."""
with tempfile.TemporaryDirectory() as temp_dir:
# Test with valid directory
self.setup_env(
{"target": "x86_64-unknown-linux-gnu", "working-directory": temp_dir}
)
validator = InputValidator("/root")
errors = validator.validate()
self.assertFalse(errors)
# Test with non-existent directory
self.setup_env(
{
"target": "x86_64-unknown-linux-gnu",
"working-directory": "/path/to/nonexistent/directory",
}
)
validator = InputValidator("/root")
errors = validator.validate()
self.assertTrue(errors)
# Test with file instead of directory
with tempfile.NamedTemporaryFile() as temp_file:
self.setup_env(
{
"target": "x86_64-unknown-linux-gnu",
"working-directory": temp_file.name,
}
)
validator = InputValidator("/root")
errors = validator.validate()
self.assertTrue(errors)
def test_validate_boolean_flags(self) -> None:
"""Test validation of boolean flags."""
boolean_flags = ["cache-cross-binary", "strip", "use-rust-cache"]
# Test valid boolean values
for flag in boolean_flags:
for value in ["true", "false"]:
self.setup_env({"target": "x86_64-unknown-linux-gnu", flag: value})
validator = InputValidator("/root")
errors = validator.validate()
self.assertFalse(errors, f"'{flag}' with '{value}' should be valid")
# Test invalid boolean values
for flag in boolean_flags:
self.setup_env({"target": "x86_64-unknown-linux-gnu", flag: "invalid"})
validator = InputValidator("/root")
errors = validator.validate()
self.assertTrue(errors, f"'{flag}' with 'invalid' should be invalid")
def test_validate_rust_cache_parameters(self) -> None:
"""Test validation of rust cache parameters."""
# Valid JSON
self.setup_env(
{
"target": "x86_64-unknown-linux-gnu",
"rust-cache-parameters": '{"key1":"value1","key2":"value2"}',
}
)
validator = InputValidator("/root")
errors = validator.validate()
self.assertFalse(errors)
# Invalid JSON
self.setup_env(
{
"target": "x86_64-unknown-linux-gnu",
"rust-cache-parameters": "{invalid json",
}
)
validator = InputValidator("/root")
errors = validator.validate()
self.assertTrue(errors)
if __name__ == "__main__":
if len(os.sys.argv) > 1 and os.sys.argv[1] == "--test":
unittest.main(argv=["unittest"])
else:
main()