mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-12 18:06:11 +02:00
Trigger credential-free Linux native fixtures for shared Runner sources, Rust and build manifests, dependency patches, and workspace inputs. Verify actual glob matching for attachment, backend, transport and dependency changes. Paid workflow authority is unchanged. Validation: 15 workflow security tests and actionlint passed. Also record 26 passing real-database authority tests, the expected old-lock negative proof, and 143 passing ACPX lifecycle regressions. Co-Authored-By: Paperclip <noreply@paperclip.ing>
148 lines
5.9 KiB
YAML
148 lines
5.9 KiB
YAML
name: Hermes Native Transport
|
|
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- .github/workflows/runner-hermes-native.yml
|
|
- packages/paperclip-runner/**
|
|
- packages/paperclip-eval-kernel/**
|
|
- packages/adapter-utils/**
|
|
- packages/shared/**
|
|
- patches/**
|
|
- package.json
|
|
- pnpm-lock.yaml
|
|
- pnpm-workspace.yaml
|
|
- tsconfig*.json
|
|
- tests/runner-e2e/provision-hermes-linux.sh
|
|
- tests/runner-e2e/workflow-security.test.ts
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: hermes-native-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
native_transport:
|
|
name: Hermes native fixture (Linux amd64, no credentials)
|
|
runs-on: ubuntu-22.04
|
|
timeout-minutes: 30
|
|
steps:
|
|
- name: Checkout source
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
with:
|
|
node-version: 24
|
|
package-manager-cache: false
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6
|
|
env:
|
|
NPM_CONFIG_AUDIT: "false"
|
|
NPM_CONFIG_FUND: "false"
|
|
NPM_CONFIG_UPDATE_NOTIFIER: "false"
|
|
with:
|
|
version: 9.15.4
|
|
|
|
- name: Qualify the job's provider Node interpreter
|
|
run: |
|
|
node <<'NODE'
|
|
const fs = require('node:fs');
|
|
const mode = fs.statSync(process.execPath).mode & 0o777;
|
|
fs.chmodSync(process.execPath, mode & ~0o022);
|
|
if ((fs.statSync(process.execPath).mode & 0o022) !== 0) {
|
|
throw new Error('provider Node interpreter remains group- or world-writable');
|
|
}
|
|
NODE
|
|
|
|
- name: Install workspace dependencies
|
|
run: |
|
|
set -euo pipefail
|
|
if ! pnpm install --frozen-lockfile; then
|
|
pnpm install --resolution-only --ignore-scripts --no-frozen-lockfile
|
|
pnpm install --frozen-lockfile
|
|
fi
|
|
|
|
- name: Restore Rust dependencies (read only)
|
|
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
with:
|
|
workspaces: packages/paperclip-runner/runner -> target
|
|
cache-workspace-crates: false
|
|
cache-bin: false
|
|
save-if: false
|
|
|
|
- name: Build verified runner and provider entrypoints
|
|
run: |
|
|
set -euo pipefail
|
|
pnpm --filter @paperclipai/paperclip-runner build:typescript
|
|
pnpm --filter @paperclipai/paperclip-runner build:binary
|
|
|
|
- name: Provision the pinned Python closure without credentials
|
|
run: |
|
|
set -euo pipefail
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends python3-venv bubblewrap
|
|
bash tests/runner-e2e/provision-hermes-linux.sh
|
|
|
|
- name: Run native fixtures against a deterministic loopback model
|
|
id: fixtures
|
|
working-directory: packages/paperclip-runner
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -m 700 "$RUNNER_TEMP/hermes-fixture-home"
|
|
# No paid environment, secrets, or credentials reach either fixture.
|
|
# The execution host must pass the real bubblewrap namespace probe.
|
|
env -i PATH="$PATH" HOME="$RUNNER_TEMP/hermes-fixture-home" \
|
|
PAPERCLIP_HERMES_QUALIFY=1 \
|
|
node --test --test-concurrency=1 scripts/qualify-hermes-runtime.test.mjs \
|
|
scripts/qualify-hermes-runnerd.test.mjs \
|
|
2>&1 | tee "$RUNNER_TEMP/hermes-native-fixture.log"
|
|
|
|
- name: Record source and runtime provenance
|
|
if: always()
|
|
env:
|
|
HERMES_FIXTURE_OUTCOME: ${{ steps.fixtures.outcome }}
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p "$RUNNER_TEMP/hermes-native-evidence"
|
|
if [ -f "$RUNNER_TEMP/hermes-native-fixture.log" ]; then
|
|
cp "$RUNNER_TEMP/hermes-native-fixture.log" "$RUNNER_TEMP/hermes-native-evidence/fixture.log"
|
|
fi
|
|
node --input-type=module <<'NODE'
|
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
import { createHash } from 'node:crypto';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { join } from 'node:path';
|
|
const root = 'packages/paperclip-runner';
|
|
const version = JSON.parse(await readFile(join(root, 'src/providers/hermes/version.json'), 'utf8'));
|
|
const manifest = JSON.parse(await readFile(join(root, 'provider-assets/hermes/linux-x64/manifest.json'), 'utf8').catch(() => 'null'));
|
|
const evidence = {
|
|
qualification: 'native transport fixture only; no paid model, browser or Daytona proof',
|
|
sourceSha: execFileSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8' }).trim(),
|
|
platform: `${process.platform}-${process.arch}`, node: process.version,
|
|
fixtureOutcome: process.env.HERMES_FIXTURE_OUTCOME,
|
|
kernel: execFileSync('uname', ['-r'], { encoding: 'utf8' }).trim(),
|
|
osRelease: await readFile('/etc/os-release', 'utf8'),
|
|
runtime: version,
|
|
closureSha256: manifest ? createHash('sha256').update(JSON.stringify(manifest.entries)).digest('hex') : null,
|
|
files: manifest?.entries?.length ?? null,
|
|
model: 'deterministic loopback fixture', credentials: 'none',
|
|
};
|
|
await writeFile(join(process.env.RUNNER_TEMP, 'hermes-native-evidence/provenance.json'), JSON.stringify(evidence, null, 2) + '\n');
|
|
NODE
|
|
|
|
- name: Upload fixture evidence
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: hermes-native-linux-amd64-${{ github.run_id }}-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/hermes-native-evidence/
|
|
if-no-files-found: warn
|
|
retention-days: 14
|