Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .github/workflows/authoring-native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,78 @@ jobs:
path: ${{ env.NATIVE_ROOT }}/evidence
if-no-files-found: error
retention-days: 14

packed:
name: Authoring / packed Linux amd64
runs-on: ubuntu-24.04
timeout-minutes: 45
env:
EXPECTED_HEAD: ${{ github.event.pull_request.head.sha || github.sha }}
PYTHONDONTWRITEBYTECODE: '1'
steps:
- name: Resolve disposable packed evidence path
shell: bash
run: |
set -euo pipefail
# Publish the path before checkout/setup so always() consumers retain it.
# Leave creation (0700) and stale-root rejection to run-packed-ci.py.
printf 'PACKED_ROOT=%s/authoring-packed-%s-%s\n' "$RUNNER_TEMP" "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" >> "$GITHUB_ENV"
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e
with:
go-version: '1.25.13'
architecture: x64
cache: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: '22.23.2'
# Use bundled npm 10.9.8; no separate package-manager migration.
check-latest: false
- name: Build, pack, execute, seal and plan at the exact checkout SHA
shell: bash
run: python3 -B scripts/run-packed-ci.py "$PACKED_ROOT" "$EXPECTED_HEAD"
- name: Require terminal packed evidence
if: always()
shell: bash
run: python3 -B scripts/check-packed-ci.py "$PACKED_ROOT" "$EXPECTED_HEAD"
- name: Preserve packed evidence including failure logs and sealed inputs
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: authoring-packed-${{ github.run_id }}-${{ github.run_attempt }}
path: |
${{ env.PACKED_ROOT }}/**
!${{ env.PACKED_ROOT }}/modules/**
!${{ env.PACKED_ROOT }}/orchestrator/**
!${{ env.PACKED_ROOT }}/planner/**
include-hidden-files: true
if-no-files-found: error
retention-days: 14

acceptance:
name: Authoring / required native and packed
needs: [native, packed]
if: always()
runs-on: ubuntu-24.04
timeout-minutes: 5
env:
REQUIRED_RESULTS: ${{ toJSON(needs) }}
PYTHONDONTWRITEBYTECODE: '1'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Check mandatory graph and focused negative controls
shell: bash
run: |
set -euo pipefail
python3 -B scripts/check-packed-workflow.py
python3 -B -m unittest discover -s scripts -p 'test_packed_ci.py'
- name: Require every native lane and packed job to succeed
if: always()
shell: bash
run: python3 -B scripts/check-packed-workflow.py --results "$REQUIRED_RESULTS"
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//go:build packedci

package commands_test

import (
"bytes"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)

type packedInputs struct {
Repo string
Projects []packedProject
Snapshots []struct{ Root string }
}

func TestPackedGeneratedPackagesReachExistingInstallerPlanner(t *testing.T) {
config := os.Getenv("UAP_PACKED_INSTALLER_CONFIG")
if config == "" {
for _, key := range []string{"UAP_PACKED_INSTALLER_CONFIG_SHA256", "UAP_PACKED_INSTALLER_COMMIT", "UAP_PACKED_INSTALLER_NODE", "UAP_PACKED_INSTALLER_OUTPUT"} {
if os.Getenv(key) != "" {
t.Fatalf("partial opt-in: %s without config", key)
}
}
t.Fatal("packedci requires terminal packed-native input")
}
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
t.Fatal("packed bridge requires Linux amd64")
}
_, file, _, _ := runtime.Caller(0)
repo := filepath.Clean(filepath.Join(filepath.Dir(file), "../../../../.."))
script := filepath.Join(repo, "npm/agentplugins/scripts/packed-installer-bridge.js")
node, digest, commit, output := os.Getenv("UAP_PACKED_INSTALLER_NODE"), os.Getenv("UAP_PACKED_INSTALLER_CONFIG_SHA256"), os.Getenv("UAP_PACKED_INSTALLER_COMMIT"), os.Getenv("UAP_PACKED_INSTALLER_OUTPUT")
if !filepath.IsAbs(node) || !filepath.IsAbs(config) || !filepath.IsAbs(output) || filepath.Clean(output) != output || len(digest) != 64 || len(commit) != 40 {
t.Fatal("complete absolute opt-in and identity pins required")
}
git := exec.Command("/usr/bin/git", "rev-parse", "HEAD")
git.Dir = repo
head, err := git.Output()
if err != nil || strings.TrimSpace(string(head)) != commit {
t.Fatalf("planner checkout is not intended commit: %v", err)
}
git = exec.Command("/usr/bin/git", "status", "--porcelain=v1", "--untracked-files=all")
git.Dir = repo
status, err := git.Output()
if err != nil || len(status) != 0 {
t.Fatalf("packed acceptance requires clean integrated checkout: %v\n%s", err, status)
}
verify := func() []byte {
t.Helper()
cmd := exec.Command(node, script, "verify", config, digest, commit)
var stderr bytes.Buffer
cmd.Stderr = &stderr
b, err := cmd.Output()
if err != nil {
t.Fatalf("sealed native intake: %v\n%s", err, stderr.String())
}
return b
}
before := verify()
var inputs packedInputs
if err := json.Unmarshal(before, &inputs); err != nil {
t.Fatal(err)
}
if inputs.Repo != repo || len(inputs.Projects) != 10 {
t.Fatal("wrong source checkout or incomplete project matrix")
}
wantProjects := map[string]bool{}
for _, product := range []string{"agentplugins", "plugin-kit-ai"} {
for _, lane := range []string{"skill", "mcp-remote", "mcp-stdio", "hybrid-remote", "hybrid-stdio"} {
wantProjects[product+"/"+lane] = true
}
}
seenSources := map[string]bool{}
for _, p := range inputs.Projects {
key := p.Product + "/" + p.Lane
if !wantProjects[key] || seenSources[p.Source] {
t.Fatal("unexpected or duplicate packed project")
}
delete(wantProjects, key)
seenSources[p.Source] = true
}
for _, s := range inputs.Snapshots {
if within(s.Root, output) || within(output, s.Root) {
t.Fatal("bridge output overlaps input")
}
}
if within(repo, output) || within(filepath.Dir(config), output) {
t.Fatal("keep bridge output outside checkout and config directory")
}
var plans []map[string]any
for _, p := range inputs.Projects {
t.Run(p.Product+"/"+p.Lane, func(t *testing.T) { plans = append(plans, packedPlanner(t, p)...) })
}
if !bytes.Equal(before, verify()) {
t.Fatal("native inputs changed during planning")
}
if t.Failed() {
return
}
if len(plans) != 30 {
t.Fatal("exactly thirty packed plans required")
}
tuples := map[string]bool{}
for _, plan := range plans {
key := fmt.Sprintf("%s/%s/%s", plan["product"], plan["lane"], plan["target"])
if tuples[key] {
t.Fatal("duplicate packed plan tuple")
}
tuples[key] = true
}
record := map[string]any{"kind": "packed-generated-existing-injected-installer-planner", "commit": commit, "config_sha256": digest, "inputs": json.RawMessage(before), "plans": plans, "release_eligible": false, "platform_acceptance": false, "attested": false}
b, err := json.MarshalIndent(record, "", " ")
if err != nil {
t.Fatal(err)
}
// Exclusive terminal evidence only after all 30 plans and preservation checks.
if resolved, err := filepath.EvalSymlinks(filepath.Dir(output)); err != nil || resolved != filepath.Dir(output) {
t.Fatal("unsafe output parent")
}
f, err := os.OpenFile(output, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
t.Fatal(err)
}
_, err = f.Write(append(b, '\n'))
closeErr := f.Close()
if err != nil || closeErr != nil {
t.Fatalf("write evidence: %v %v", err, closeErr)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package commands_test

// Packed acceptance is opt-in and consumes ROOT's completed, pinned npm run.
// The separate source harness below tests this seam, never packed acceptance.
// Shared planner fixtures remain in ordinary native coverage.
import (
"bytes"
"context"
Expand All @@ -11,7 +10,6 @@ import (
"fmt"
"io/fs"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"
Expand All @@ -32,100 +30,6 @@ import (
)

type packedProject struct{ Product, Lane, Source string }
type packedInputs struct {
Repo string
Projects []packedProject
Snapshots []struct{ Root string }
}

func TestPackedGeneratedPackagesReachExistingInstallerPlanner(t *testing.T) {
config := os.Getenv("UAP_PACKED_INSTALLER_CONFIG")
if config == "" {
for _, key := range []string{"UAP_PACKED_INSTALLER_CONFIG_SHA256", "UAP_PACKED_INSTALLER_COMMIT", "UAP_PACKED_INSTALLER_NODE", "UAP_PACKED_INSTALLER_OUTPUT"} {
if os.Getenv(key) != "" {
t.Fatalf("partial opt-in: %s without config", key)
}
}
t.Skip("ROOT-owned terminal packed-native input required")
}
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
t.Fatal("packed bridge requires Linux amd64")
}
_, file, _, _ := runtime.Caller(0)
repo := filepath.Clean(filepath.Join(filepath.Dir(file), "../../../../.."))
script := filepath.Join(repo, "npm/agentplugins/scripts/packed-installer-bridge.js")
node, digest, commit, output := os.Getenv("UAP_PACKED_INSTALLER_NODE"), os.Getenv("UAP_PACKED_INSTALLER_CONFIG_SHA256"), os.Getenv("UAP_PACKED_INSTALLER_COMMIT"), os.Getenv("UAP_PACKED_INSTALLER_OUTPUT")
if !filepath.IsAbs(node) || !filepath.IsAbs(config) || !filepath.IsAbs(output) || filepath.Clean(output) != output || len(digest) != 64 || len(commit) != 40 {
t.Fatal("complete absolute opt-in and identity pins required")
}
git := exec.Command("/usr/bin/git", "rev-parse", "HEAD")
git.Dir = repo
head, err := git.Output()
if err != nil || strings.TrimSpace(string(head)) != commit {
t.Fatalf("planner checkout is not intended commit: %v", err)
}
git = exec.Command("/usr/bin/git", "status", "--porcelain=v1", "--untracked-files=all")
git.Dir = repo
status, err := git.Output()
if err != nil || len(status) != 0 {
t.Fatalf("packed acceptance requires clean integrated checkout: %v\n%s", err, status)
}
verify := func() []byte {
t.Helper()
cmd := exec.Command(node, script, "verify", config, digest, commit)
var stderr bytes.Buffer
cmd.Stderr = &stderr
b, err := cmd.Output()
if err != nil {
t.Fatalf("sealed native intake: %v\n%s", err, stderr.String())
}
return b
}
before := verify()
var inputs packedInputs
if err := json.Unmarshal(before, &inputs); err != nil {
t.Fatal(err)
}
if inputs.Repo != repo || len(inputs.Projects) != 10 {
t.Fatal("wrong source checkout or incomplete project matrix")
}
for _, s := range inputs.Snapshots {
if within(s.Root, output) || within(output, s.Root) {
t.Fatal("bridge output overlaps input")
}
}
if within(repo, output) || within(filepath.Dir(config), output) {
t.Fatal("keep bridge output outside checkout and config directory")
}
var plans []map[string]any
for _, p := range inputs.Projects {
t.Run(p.Product+"/"+p.Lane, func(t *testing.T) { plans = append(plans, packedPlanner(t, p)...) })
}
if !bytes.Equal(before, verify()) {
t.Fatal("native inputs changed during planning")
}
if t.Failed() {
return
}
record := map[string]any{"kind": "packed-generated-existing-injected-installer-planner", "commit": commit, "config_sha256": digest, "inputs": json.RawMessage(before), "plans": plans, "release_eligible": false, "platform_acceptance": false, "attested": false}
b, err := json.MarshalIndent(record, "", " ")
if err != nil {
t.Fatal(err)
}
// Exclusive terminal evidence only after all 30 plans and preservation checks.
if resolved, err := filepath.EvalSymlinks(filepath.Dir(output)); err != nil || resolved != filepath.Dir(output) {
t.Fatal("unsafe output parent")
}
f, err := os.OpenFile(output, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
t.Fatal(err)
}
_, err = f.Write(append(b, '\n'))
closeErr := f.Close()
if err != nil || closeErr != nil {
t.Fatalf("write evidence: %v %v", err, closeErr)
}
}

func within(root, p string) bool {
return p == root || strings.HasPrefix(p, root+string(filepath.Separator))
Expand Down Expand Up @@ -316,8 +220,8 @@ func packedPlanner(t *testing.T, p packedProject) []map[string]any {
}

func TestPackedInstallerSourceHarness(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("disposable Linux source harness only")
if (runtime.GOOS != "linux" && runtime.GOOS != "windows") || (runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64") {
t.Skip("source harness requires supported Linux/Windows amd64/arm64 host")
}
author := commands.App{Projects: project.Service{Scratch: t.TempDir()}, Revision: publicRevision, PublicContract: true}
for _, lane := range []string{"skill", "mcp-remote", "mcp-stdio", "hybrid-remote", "hybrid-stdio"} {
Expand Down
Loading
Loading