Skip to content

Commit c6e8d22

Browse files
Copilotintel352
andauthored
Add strict-contracts CI job, strengthen contract tests, add engine manifest validation
Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-github/sessions/f07d93ad-41a2-4378-bba2-410c8ca11dc9 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
1 parent 10d5c65 commit c6e8d22

2 files changed

Lines changed: 67 additions & 1 deletion

File tree

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,35 @@ jobs:
1414
go-version-file: go.mod
1515
- run: go build ./...
1616
- run: go test ./... -v -race -count=1
17+
env:
18+
GOPRIVATE: github.com/GoCodeAlone/*
19+
GONOSUMCHECK: github.com/GoCodeAlone/*
20+
21+
strict-contracts:
22+
name: Validate strict plugin contracts
23+
runs-on: [self-hosted, Linux, X64]
24+
permissions:
25+
contents: read
26+
steps:
27+
- uses: actions/checkout@v6
28+
- name: Verify plugin.json exists
29+
run: |
30+
test -f plugin.json || { echo "ERROR: plugin.json is missing — every release must include a strict contract manifest"; exit 1; }
31+
- uses: actions/setup-go@v6
32+
with:
33+
go-version-file: go.mod
34+
- name: Run strict contract tests
35+
run: |
36+
go test ./internal/... -run "TestPluginStepSchemasJSON|TestPluginManifestEngineValidation|TestModuleSchemas" -v -count=1
37+
env:
38+
GOPRIVATE: github.com/GoCodeAlone/*
39+
GONOSUMCHECK: github.com/GoCodeAlone/*
40+
- name: Validate plugin.json with wfctl
41+
run: |
42+
# wfctl validates registry-format manifests; strict contract schema coverage is enforced
43+
# by the Go tests above. This step runs informational validation and logs the result.
44+
go run github.com/GoCodeAlone/workflow/cmd/wfctl@v0.3.56 plugin validate --file plugin.json 2>&1; wfctl_exit=$?
45+
echo "wfctl validation exit code: ${wfctl_exit}"
46+
env:
47+
GOPRIVATE: github.com/GoCodeAlone/*
48+
GONOSUMCHECK: github.com/GoCodeAlone/*

internal/schemas_test.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"encoding/json"
55
"os"
66
"testing"
7+
8+
"github.com/GoCodeAlone/workflow/plugin"
79
)
810

911
// TestModuleSchemas verifies that the plugin's SchemaProvider returns schema
@@ -77,7 +79,7 @@ func TestPluginStepSchemasJSON(t *testing.T) {
7779
// Locate plugin.json relative to the repository root (one level up from internal/).
7880
data, err := os.ReadFile("../plugin.json")
7981
if err != nil {
80-
t.Skipf("plugin.json not found (skipping in isolated test environments): %v", err)
82+
t.Fatalf("plugin.json not found — every build must ship a contract manifest: %v", err)
8183
}
8284

8385
var manifest struct {
@@ -110,3 +112,35 @@ func TestPluginStepSchemasJSON(t *testing.T) {
110112
len(manifest.StepSchemas), len(manifest.StepTypes))
111113
}
112114
}
115+
116+
// TestPluginManifestEngineValidation verifies that plugin.json is parseable as a
117+
// workflow engine PluginManifest and that Validate() passes required-field checks.
118+
func TestPluginManifestEngineValidation(t *testing.T) {
119+
m, err := plugin.LoadManifest("../plugin.json")
120+
if err != nil {
121+
t.Fatalf("plugin.LoadManifest: %v", err)
122+
}
123+
if err := m.Validate(); err != nil {
124+
t.Fatalf("plugin.json fails engine manifest validation: %v", err)
125+
}
126+
// Strict contract requirements: must declare at least one module or step type.
127+
if len(m.ModuleTypes) == 0 && len(m.StepTypes) == 0 {
128+
t.Error("plugin.json: must advertise at least one moduleType or stepType for strict contracts")
129+
}
130+
// StepSchemas must be present when step types are declared.
131+
if len(m.StepTypes) > 0 && len(m.StepSchemas) == 0 {
132+
t.Error("plugin.json: stepSchemas is required when stepTypes are declared (missing_step_contract_descriptor)")
133+
}
134+
// Every step type must have a schema entry.
135+
schemaSet := make(map[string]bool, len(m.StepSchemas))
136+
for _, s := range m.StepSchemas {
137+
if s != nil {
138+
schemaSet[s.Type] = true
139+
}
140+
}
141+
for _, st := range m.StepTypes {
142+
if !schemaSet[st] {
143+
t.Errorf("plugin.json: stepType %q has no stepSchema (missing_step_contract_descriptor)", st)
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)