Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/patch-import-safe-outputs.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

479 changes: 476 additions & 3 deletions .github/workflows/notion-issue-summary.lock.yml

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions pkg/parser/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,59 @@ func compileSchema(schemaJSON, schemaURL string) (*jsonschema.Schema, error) {
return schema, nil
}

// safeOutputMetaFields are the meta-configuration fields in safe-outputs that are NOT actual safe output types.
// These are used for configuration, not for defining safe output operations.
var safeOutputMetaFields = map[string]bool{
"allowed-domains": true,
"staged": true,
"env": true,
"github-token": true,
"app": true,
"max-patch-size": true,
"jobs": true,
"runs-on": true,
}

// GetSafeOutputTypeKeys returns the list of safe output type keys from the embedded main workflow schema.
// These are the keys under safe-outputs that define actual safe output operations (like create-issue, add-comment, etc.)
// Meta-configuration fields (like allowed-domains, staged, env, etc.) are excluded.
func GetSafeOutputTypeKeys() ([]string, error) {
// Parse the embedded schema JSON
var schemaDoc map[string]any
if err := json.Unmarshal([]byte(mainWorkflowSchema), &schemaDoc); err != nil {
return nil, fmt.Errorf("failed to parse main workflow schema: %w", err)
}

// Navigate to properties.safe-outputs.properties
properties, ok := schemaDoc["properties"].(map[string]any)
if !ok {
return nil, errors.New("schema missing 'properties' field")
}

safeOutputs, ok := properties["safe-outputs"].(map[string]any)
if !ok {
return nil, errors.New("schema missing 'properties.safe-outputs' field")
}

safeOutputsProperties, ok := safeOutputs["properties"].(map[string]any)
if !ok {
return nil, errors.New("schema missing 'properties.safe-outputs.properties' field")
}

// Extract keys that are actual safe output types (not meta-configuration)
var keys []string
for key := range safeOutputsProperties {
if !safeOutputMetaFields[key] {
keys = append(keys, key)
}
}

// Sort keys for consistent ordering
sort.Strings(keys)

return keys, nil
}

func validateWithSchema(frontmatter map[string]any, schemaJSON, context string) error {
// Determine which cached schema to use based on the schemaJSON
var schema *jsonschema.Schema
Expand Down
58 changes: 58 additions & 0 deletions pkg/parser/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1660,3 +1660,61 @@ func TestValidateMCPConfigWithSchema(t *testing.T) {
})
}
}

// TestGetSafeOutputTypeKeys tests extracting safe output type keys from the embedded schema
func TestGetSafeOutputTypeKeys(t *testing.T) {
keys, err := GetSafeOutputTypeKeys()
if err != nil {
t.Fatalf("GetSafeOutputTypeKeys() returned error: %v", err)
}

// Should return multiple keys
if len(keys) == 0 {
t.Error("GetSafeOutputTypeKeys() returned empty list")
}

// Should include known safe output types
expectedKeys := []string{
"create-issue",
"add-comment",
"create-discussion",
"create-pull-request",
"update-issue",
}

keySet := make(map[string]bool)
for _, key := range keys {
keySet[key] = true
}

for _, expected := range expectedKeys {
if !keySet[expected] {
t.Errorf("GetSafeOutputTypeKeys() missing expected key: %s", expected)
}
}

// Should NOT include meta-configuration fields
metaFields := []string{
"allowed-domains",
"staged",
"env",
"github-token",
"app",
"max-patch-size",
"jobs",
"runs-on",
}

for _, meta := range metaFields {
if keySet[meta] {
t.Errorf("GetSafeOutputTypeKeys() should not include meta field: %s", meta)
}
}

// Keys should be sorted
for i := 1; i < len(keys); i++ {
if keys[i-1] > keys[i] {
t.Errorf("GetSafeOutputTypeKeys() keys are not sorted: %s > %s", keys[i-1], keys[i])
}
}
}
7 changes: 7 additions & 0 deletions pkg/workflow/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,13 @@ func (c *Compiler) ParseWorkflowFile(markdownPath string) (*WorkflowData, error)
workflowData.SafeOutputs.App = includedApp
}

// Merge safe-outputs types from imports (create-issue, add-comment, etc.)
mergedSafeOutputs, err := c.MergeSafeOutputs(workflowData.SafeOutputs, allSafeOutputsConfigs)
if err != nil {
return nil, fmt.Errorf("failed to merge safe-outputs from imports: %w", err)
}
workflowData.SafeOutputs = mergedSafeOutputs

// Parse the "on" section for command triggers, reactions, and other events
err = c.parseOnSection(result.Frontmatter, workflowData, markdownPath)
if err != nil {
Expand Down
Loading
Loading