name: CI
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
branches: [main]
workflow_dispatch:
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 - run: cargo fmt --check
- run: cargo clippy --all-features --all-targets -- -D warnings
- uses: EmbarkStudios/cargo-deny-action@bb137d7af7e4fb67e5f82a49c4fce4fad40782fe - uses: taiki-e/install-action@f092c064826410a38929a5791d2c0225b94432fe with:
tool: cargo-audit
- run: cargo audit --ignore RUSTSEC-2023-0071
- name: Check version parity (Cargo.toml vs node/package.json)
run: |
cargo_ver=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)
node_ver=$(sed -n 's/.*"version": "\(.*\)".*/\1/p' node/package.json | head -1)
if [ "$cargo_ver" != "$node_ver" ]; then
echo "::error::Version mismatch: Cargo.toml=$cargo_ver node/package.json=$node_ver"
exit 1
fi
msrv:
name: MSRV
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 with:
toolchain: "1.89"
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 - run: cargo check --all-features --all-targets --locked
test:
name: Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 - uses: taiki-e/install-action@f092c064826410a38929a5791d2c0225b94432fe - run: cargo nextest run --all-features --profile ci
- uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 if: always()
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: target/nextest/ci/junit.xml
test-gate:
name: Test
runs-on: ubuntu-latest
needs: test
if: always()
permissions: {}
steps:
- run: |
if [[ "${{ needs.test.result }}" != "success" ]]; then
echo "Test matrix failed"
exit 1
fi
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 - uses: taiki-e/install-action@f092c064826410a38929a5791d2c0225b94432fe with:
tool: cargo-llvm-cov
- run: cargo llvm-cov --codecov --output-path codecov.json -- --test-threads=1
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f with:
token: ${{ secrets.CODECOV_TOKEN }}
files: codecov.json
fail_ci_if_error: false
demo-test:
name: VHS Dress Rehearsal
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 - run: sudo apt-get install -y direnv
- run: make test-demos
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
with:
name: murk-linux
path: target/release/murk
retention-days: 1
install-smoke:
name: Install smoke (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 - run: cargo build --release
- name: Smoke-test install.sh against a local fixture
shell: bash
run: |
set -euo pipefail
target=$(rustc -vV | sed -n 's/^host: //p')
tag=v0.0.0-smoke
archive="murk-${tag}-${target}.tar.gz"
# Build a fixture shaped like a real GitHub release: a tarball holding
# the murk binary, plus a matching SHA256SUMS.
rel="$RUNNER_TEMP/release"
mkdir -p "$rel" "$RUNNER_TEMP/stage"
cp target/release/murk "$RUNNER_TEMP/stage/murk"
tar czf "$rel/$archive" -C "$RUNNER_TEMP/stage" murk
if command -v sha256sum >/dev/null; then
( cd "$rel" && sha256sum "$archive" > SHA256SUMS )
else
( cd "$rel" && shasum -a 256 "$archive" > SHA256SUMS )
fi
# Serve the fixture and install through install.sh as a fresh user
# would, pointed at the fixture instead of github.com.
python3 -m http.server 8099 --directory "$rel" >/dev/null 2>&1 &
server=$!
trap 'kill "$server" 2>/dev/null || true' EXIT
for _ in $(seq 1 40); do
curl -fsS http://localhost:8099/SHA256SUMS -o /dev/null 2>/dev/null && break
sleep 0.25
done
bindir="$RUNNER_TEMP/bin"
mkdir -p "$bindir"
MURK_TAG="$tag" \
MURK_BASE_URL=http://localhost:8099 \
MURK_SKIP_ATTESTATION=1 \
MURK_INSTALL_DIR="$bindir" \
sh install.sh
# The installed binary must start and complete an encrypt/decrypt
# roundtrip in a clean temp directory with an isolated HOME.
export PATH="$bindir:$PATH"
murk --version
export HOME="$RUNNER_TEMP/home"
vault="$RUNNER_TEMP/vault"
mkdir -p "$HOME" "$vault"
cd "$vault"
printf 'smoke-user\n' | murk init
. ./.env
printf 'hunter2\n' | murk add SMOKE_KEY
got=$(murk get SMOKE_KEY)
test "$got" = "hunter2"
echo "install smoke passed: install.sh + init/add/get roundtrip"
vhs-record:
name: VHS (${{ matrix.tape }})
needs: demo-test
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
tape: [hero, team, offboard, eve, recovery, github, direnv, mallory, ssh]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with:
name: murk-linux
path: target/release/
- run: chmod +x target/release/murk
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c - name: Build VHS image with git and direnv
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a with:
context: .github/vhs
tags: vhs-git
load: true
cache-from: type=gha,scope=vhs-git
cache-to: type=gha,mode=max,scope=vhs-git
- name: Check binary runs inside the vhs image
run: docker run --rm --entrypoint /vhs/target/release/murk -v "$PWD":/vhs vhs-git --version
- name: Record tape
run: docker run --rm -v "$PWD":/vhs -e PATH="/vhs/target/release:$PATH" vhs-git demo/${{ matrix.tape }}.tape
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a with:
name: gif-${{ matrix.tape }}
path: demo/${{ matrix.tape }}.gif
retention-days: 1
vhs:
name: VHS
needs: vhs-record
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
concurrency:
group: vhs-publish-demo
cancel-in-progress: false
permissions:
contents: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with:
pattern: gif-*
merge-multiple: true
path: demo/
- uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./demo
publish_branch: demo
keep_files: true