diff --git a/.github/workflows/release_build_infisical_cli.yml b/.github/workflows/release_build_infisical_cli.yml index a131266c..c2f9c1a8 100644 --- a/.github/workflows/release_build_infisical_cli.yml +++ b/.github/workflows/release_build_infisical_cli.yml @@ -16,7 +16,7 @@ on: permissions: contents: write - id-token: write # Required for NPM OIDC auth for releases + id-token: write # Required for NPM OIDC auth for releases jobs: validate-tag-branch: @@ -78,7 +78,7 @@ jobs: - name: Setup Node uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: - node-version: '24.14.0' + node-version: "24.14.0" cache: "npm" cache-dependency-path: ./npm/package-lock.json registry-url: "https://registry.npmjs.org" @@ -205,50 +205,6 @@ jobs: name: goreleaser-dist-linux path: dist/ retention-days: 7 - - name: Smoke test linux binary across supported distros - if: github.event_name == 'workflow_dispatch' && inputs.dry_run - run: | - set -uo pipefail - fail=0 - echo "::group::Static-link assertion (file)" - for d in dist/linux-*-rdp_linux_*; do - bin="$d/infisical" - [ -f "$bin" ] || continue - info=$(file "$bin") - echo "$info" - if ! echo "$info" | grep -q "statically linked"; then - echo "::error file=$bin::not statically linked" - fail=1 - fi - done - echo "::endgroup::" - - BIN=dist/linux-amd64-rdp_linux_amd64_v1/infisical - if [ ! -f "$BIN" ]; then - echo "::error::expected $BIN missing from dist/" - exit 1 - fi - echo "::group::Smoke test linux-amd64 binary across distro floor" - for img in \ - ubuntu:22.04 \ - ubuntu:20.04 \ - rockylinux:9 \ - rockylinux:8 \ - amazonlinux:2023 \ - amazonlinux:2 \ - alpine:3.19 \ - gcr.io/distroless/static-debian12; do - echo "--- $img ---" - if ! docker run --rm --platform linux/amd64 \ - -v "$PWD/$BIN":/infisical:ro \ - "$img" /infisical --version; then - echo "::error::binary failed to run on $img" - fail=1 - fi - done - echo "::endgroup::" - - [ "$fail" -eq 0 ] || exit 1 - name: GoReleaser (release) if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) uses: goreleaser/goreleaser-action@5fdedb94abba051217030cc86d4523cf3f02243d # v4.6.0 @@ -469,5 +425,3 @@ jobs: name: goreleaser-dist-windows path: dist/ retention-days: 7 - - diff --git a/.github/workflows/run-cli-rdp-smoke.yml b/.github/workflows/run-cli-rdp-smoke.yml deleted file mode 100644 index 74fa474d..00000000 --- a/.github/workflows/run-cli-rdp-smoke.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: RDP Bridge Smoke Test - -on: - pull_request: - types: [opened, synchronize] - workflow_dispatch: - -jobs: - smoke: - name: Build + smoke test on linux/amd64 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Set up Go - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 - with: - go-version: "1.25.9" - - - name: Cache cargo registry + target - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - packages/pam/handlers/rdp/native/target - key: rdp-bridge-cargo-${{ runner.os }}-${{ hashFiles('packages/pam/handlers/rdp/native/Cargo.lock') }} - restore-keys: rdp-bridge-cargo-${{ runner.os }}- - - - name: Install pinned Rust toolchain - working-directory: packages/pam/handlers/rdp/native - run: rustup show active-toolchain - - - name: cargo fmt --check - working-directory: packages/pam/handlers/rdp/native - run: cargo fmt --check - - - name: cargo clippy -D warnings - working-directory: packages/pam/handlers/rdp/native - run: cargo clippy --all-targets -- -D warnings - - - name: cargo build --release - working-directory: packages/pam/handlers/rdp/native - run: cargo build --release - - - name: go build -tags rdp - run: go build -tags rdp -o ./infisical-rdp . - - - name: Smoke test CLI - run: | - ./infisical-rdp --version - ./infisical-rdp pam rdp access --help diff --git a/.github/workflows/run-cli-smoke-tests.yml b/.github/workflows/run-cli-smoke-tests.yml new file mode 100644 index 00000000..1c7928b7 --- /dev/null +++ b/.github/workflows/run-cli-smoke-tests.yml @@ -0,0 +1,169 @@ +name: CLI Distro Smoke Tests + +on: + pull_request: + types: [opened, synchronize] + paths: + - "**.go" + - "go.mod" + - "go.sum" + - ".goreleaser.yaml" + - "packages/pam/handlers/rdp/native/**" + - "smoke-tests/**" + - ".github/workflows/run-cli-smoke-tests.yml" + + workflow_dispatch: + workflow_call: + +jobs: + build: + name: Build CLI + packages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Set up Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version: "1.25.9" + + - name: Cache cargo registry + target + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + packages/pam/handlers/rdp/native/target + key: rdp-smoke-cargo-${{ runner.os }}-${{ hashFiles('packages/pam/handlers/rdp/native/Cargo.lock') }} + restore-keys: rdp-smoke-cargo-${{ runner.os }}- + + - name: Install pinned Rust toolchain + working-directory: packages/pam/handlers/rdp/native + run: rustup show active-toolchain + + - name: cargo fmt --check + working-directory: packages/pam/handlers/rdp/native + run: cargo fmt --check + + - name: cargo clippy -D warnings + working-directory: packages/pam/handlers/rdp/native + run: cargo clippy --all-targets -- -D warnings + + - name: Install cross + run: cargo install cross --locked --version 0.2.5 + + - name: Build RDP bridge for musl + working-directory: packages/pam/handlers/rdp/native + run: cross build --release --target x86_64-unknown-linux-musl + + - name: Install musl cross-compiler + run: | + set -euo pipefail + MUSL_CROSS_TAG=20260430 + sudo mkdir -p /opt/musl-cross + triple=x86_64-unknown-linux-musl + sha=2495cfe18fc1f406d5cab93d902176af75a78f0ae93137f3e8b2df7708ec32fa + tarball="/tmp/${triple}.tar.xz" + curl --retry 5 --retry-delay 10 --retry-all-errors \ + --connect-timeout 30 --max-time 240 \ + -fsSL "https://github.com/cross-tools/musl-cross/releases/download/${MUSL_CROSS_TAG}/${triple}.tar.xz" \ + -o "$tarball" + echo "${sha} ${tarball}" | sha256sum -c - + sudo tar -xJ -f "$tarball" -C /opt/musl-cross + rm -f "$tarball" + echo "/opt/musl-cross/${triple}/bin" >> "$GITHUB_PATH" + + - name: Build static binary + run: | + CGO_ENABLED=1 \ + CC=x86_64-unknown-linux-musl-gcc \ + CGO_LDFLAGS="-L packages/pam/handlers/rdp/native/target/x86_64-unknown-linux-musl/release" \ + go build -trimpath \ + -tags=rdp,osusergo,netgo \ + -ldflags "-X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION=0.0.0-smoke -extldflags '-static'" \ + -o infisical . + + - name: Install nfpm + run: | + go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.46.3 + + - name: Create packages + run: | + mkdir -p smoke-tests/dist + nfpm package --config smoke-tests/nfpm.yaml --packager deb --target smoke-tests/dist/infisical.deb + nfpm package --config smoke-tests/nfpm.yaml --packager rpm --target smoke-tests/dist/infisical.rpm + nfpm package --config smoke-tests/nfpm.yaml --packager apk --target smoke-tests/dist/infisical.apk + nfpm package --config smoke-tests/nfpm.yaml --packager archlinux --target smoke-tests/dist/infisical.pkg.tar.zst + + - name: Upload packages + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: smoke-test-packages + path: | + smoke-tests/dist/ + smoke-tests/smoke.sh + retention-days: 1 + + smoke-test: + name: ${{ matrix.distro }} + needs: build + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - distro: ubuntu-22.04 + image: ubuntu:22.04 + pkg: infisical.deb + install: "dpkg -i" + + - distro: ubuntu-24.04 + image: ubuntu:24.04 + pkg: infisical.deb + install: "dpkg -i" + + - distro: debian-12 + image: debian:12 + pkg: infisical.deb + install: "dpkg -i" + + - distro: fedora-40 + image: fedora:40 + pkg: infisical.rpm + install: "rpm -i" + + - distro: rockylinux-9 + image: rockylinux:9 + pkg: infisical.rpm + install: "rpm -i" + + - distro: amazonlinux-2023 + image: amazonlinux:2023 + pkg: infisical.rpm + install: "rpm -i" + + - distro: alpine-3.20 + image: alpine:3.20 + pkg: infisical.apk + install: "apk add --allow-untrusted" + + - distro: archlinux + image: archlinux:latest + pkg: infisical.pkg.tar.zst + install: "pacman -U --noconfirm" + + steps: + - name: Download packages + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: smoke-test-packages + path: artifacts + + - name: Run smoke tests on ${{ matrix.distro }} + run: | + chmod +x artifacts/smoke.sh + docker run --rm \ + -v "${{ github.workspace }}/artifacts/dist:/dist" \ + -v "${{ github.workspace }}/artifacts/smoke.sh:/smoke.sh" \ + ${{ matrix.image }} \ + sh -c "${{ matrix.install }} /dist/${{ matrix.pkg }} && /smoke.sh" diff --git a/smoke-tests/nfpm.yaml b/smoke-tests/nfpm.yaml new file mode 100644 index 00000000..a41149e0 --- /dev/null +++ b/smoke-tests/nfpm.yaml @@ -0,0 +1,12 @@ +name: infisical +arch: amd64 +platform: linux +version: v0.0.0-smoke +maintainer: "Infisical, Inc" +description: "The official Infisical CLI" +homepage: "https://infisical.com/" +license: MIT + +contents: + - src: ./infisical + dst: /usr/bin/infisical diff --git a/smoke-tests/smoke.sh b/smoke-tests/smoke.sh new file mode 100755 index 00000000..a3d3e9ab --- /dev/null +++ b/smoke-tests/smoke.sh @@ -0,0 +1,82 @@ +#!/bin/sh +set -e + +DISTRO="unknown" +if [ -f /etc/os-release ]; then + DISTRO=$(. /etc/os-release && echo "$PRETTY_NAME") +fi + +echo "=== CLI Smoke Tests ===" +echo "Distro: $DISTRO" +echo "Arch: $(uname -m)" +echo "" + +passed=0 +failed=0 + +pass() { + passed=$((passed + 1)) + echo "PASS: $1" +} + +fail() { + failed=$((failed + 1)) + echo "FAIL: $1" +} + +if ! command -v infisical >/dev/null 2>&1; then + fail "infisical binary not found in PATH" + exit 1 +fi +pass "binary found at $(command -v infisical)" + +# --version +if output=$(infisical --version 2>&1); then + pass "--version ($output)" +else + fail "--version exited with $?" +fi + +# --help +if infisical --help >/dev/null 2>&1; then + pass "--help" +else + fail "--help" +fi + +# core subcommands +for cmd in secrets run export login agent gateway pam; do + if infisical "$cmd" --help >/dev/null 2>&1; then + pass "$cmd --help" + else + fail "$cmd --help" + fi +done + +# RDP bridge subcommand (verifies the Rust bridge linked correctly) +if infisical pam rdp access --help >/dev/null 2>&1; then + pass "pam rdp access --help" +else + fail "pam rdp access --help" +fi + +# shared library check +BINARY_PATH=$(command -v infisical) +if command -v ldd >/dev/null 2>&1; then + ldd_output=$(ldd "$BINARY_PATH" 2>&1 || true) + if echo "$ldd_output" | grep -qi "not a dynamic executable\|statically linked\|not a valid dynamic program"; then + pass "static binary (no dynamic dependencies)" + elif echo "$ldd_output" | grep -qi "not found"; then + fail "missing shared libraries" + echo "$ldd_output" + else + pass "no missing shared libraries" + fi +fi + +echo "" +echo "Results: $passed passed, $failed failed" + +if [ "$failed" -gt 0 ]; then + exit 1 +fi