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
13 changes: 5 additions & 8 deletions .github/instructions/developer.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,11 @@ The custom actions build system is **entirely implemented in Go** in `pkg/cli/ac
**Directory Structure**:
```
actions/
├── setup-safe-inputs/
│ ├── action.yml
│ ├── index.js
│ └── src/
├── setup-safe-outputs/
│ ├── action.yml
│ ├── index.js
│ └── src/
└── setup/
├── action.yml
├── setup.sh
├── js/
└── sh/
```

**Implementation**: See specs/actions.md and `pkg/cli/actions_build_command.go`
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ trivy-results.sarif
# Note: If workflows fail due to missing js/ files, these may need to be committed
# The js/ directories contain compiled JavaScript from pkg/workflow/js/*.cjs
# and are generated by 'make actions-build'
actions/setup-safe-outputs/js/

# License compliance reports
licenses.csv
Expand Down
14 changes: 1 addition & 13 deletions actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,6 @@ Copies workflow script files to the agent environment. This action embeds all ne

[Documentation](./setup/README.md)

### setup-safe-outputs

Copies safe-outputs MCP server files to the agent environment. This action embeds all necessary JavaScript files for the safe-outputs MCP server and copies them to a specified destination directory.

[Documentation](./setup-safe-outputs/README.md)

### setup-safe-inputs

Copies safe-inputs MCP server files to the agent environment. This action embeds all necessary JavaScript files for the safe-inputs MCP server and copies them to a specified destination directory.

[Documentation](./setup-safe-inputs/README.md)

### noop

Processes noop safe output - a fallback output type that logs messages for transparency without taking any GitHub API actions.
Expand Down Expand Up @@ -264,7 +252,7 @@ Test actions locally by:
1. Creating a test workflow in `.github/workflows/`
2. Using the action with a local path:
```yaml
- uses: ./actions/setup-safe-outputs
- uses: ./actions/setup
with:
destination: /tmp/test
```
Expand Down
102 changes: 2 additions & 100 deletions pkg/cli/actions_build_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ func ActionsCleanCommand() error {

cleanedCount := 0
for _, actionName := range actionDirs {
// Clean index.js for actions that use it (except setup-safe-outputs and setup)
if actionName != "setup-safe-outputs" && actionName != "setup" {
// Clean index.js for actions that use it (except setup)
if actionName != "setup" {
indexPath := filepath.Join(actionsDir, actionName, "index.js")
if _, err := os.Stat(indexPath); err == nil {
if err := os.Remove(indexPath); err != nil {
Expand All @@ -117,18 +117,6 @@ func ActionsCleanCommand() error {
}
}

// Clean js/ directory for setup-safe-outputs
if actionName == "setup-safe-outputs" {
jsDir := filepath.Join(actionsDir, actionName, "js")
if _, err := os.Stat(jsDir); err == nil {
if err := os.RemoveAll(jsDir); err != nil {
return fmt.Errorf("failed to remove %s: %w", jsDir, err)
}
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ Removed %s/js/", actionName)))
cleanedCount++
}
}

// For setup action, both js/ and sh/ directories are source of truth (NOT generated)
// Do not clean them
}
Expand Down Expand Up @@ -219,11 +207,6 @@ func buildAction(actionsDir, actionName string) error {
return err
}

// Special handling for setup-safe-outputs: copy files instead of embedding
if actionName == "setup-safe-outputs" {
return buildSetupSafeOutputsAction(actionsDir, actionName)
}

// Special handling for setup: build shell script with embedded files
if actionName == "setup" {
return buildSetupAction(actionsDir, actionName)
Expand Down Expand Up @@ -287,43 +270,6 @@ func buildAction(actionsDir, actionName string) error {
return nil
}

// buildSetupSafeOutputsAction builds the setup-safe-outputs action by copying JavaScript files
func buildSetupSafeOutputsAction(actionsDir, actionName string) error {
actionPath := filepath.Join(actionsDir, actionName)
jsDir := filepath.Join(actionPath, "js")

// Get dependencies for this action
dependencies := getActionDependencies(actionName)
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ Found %d dependencies", len(dependencies))))

// Get all JavaScript sources
sources := workflow.GetJavaScriptSources()

// Create js directory if it doesn't exist
if err := os.MkdirAll(jsDir, 0755); err != nil {
return fmt.Errorf("failed to create js directory: %w", err)
}

// Copy each dependency file to the js directory
copiedCount := 0
for _, dep := range dependencies {
if content, ok := sources[dep]; ok {
destPath := filepath.Join(jsDir, dep)
if err := os.WriteFile(destPath, []byte(content), 0644); err != nil {
return fmt.Errorf("failed to write %s: %w", dep, err)
}
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" - %s", dep)))
copiedCount++
} else {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf(" ⚠ Warning: Could not find %s", dep)))
}
}

fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf(" ✓ Copied %d files to js/", copiedCount)))

return nil
}

// buildSetupAction builds the setup action by checking that source files exist.
// Note: Both JavaScript and shell scripts are source of truth in actions/setup/js/ and actions/setup/sh/
// They get synced to pkg/workflow/js/ and pkg/workflow/sh/ during the build process via Makefile targets.
Expand Down Expand Up @@ -374,49 +320,5 @@ func getActionDependencies(actionName string) []string {
return workflow.GetAllScriptFilenames()
}

// Static dependencies for other actions
dependencyMap := map[string][]string{
"setup-safe-outputs": {
"safe_outputs_mcp_server.cjs",
"safe_outputs_bootstrap.cjs",
"safe_outputs_tools_loader.cjs",
"safe_outputs_config.cjs",
"safe_outputs_handlers.cjs",
"mcp_server_core.cjs",
"mcp_logger.cjs",
"messages.cjs",
},
"setup-safe-inputs": {
"safe_inputs_mcp_server.cjs",
"safe_inputs_bootstrap.cjs",
"safe_inputs_config_loader.cjs",
"safe_inputs_tool_factory.cjs",
"safe_inputs_validation.cjs",
"mcp_server_core.cjs",
"mcp_logger.cjs",
},
"noop": {
"load_agent_output.cjs",
},
"minimize_comment": {
"load_agent_output.cjs",
},
"close_issue": {
"close_entity_helpers.cjs",
},
"close_pull_request": {
"close_entity_helpers.cjs",
},
"close_discussion": {
"generate_footer.cjs",
"get_repository_url.cjs",
"get_tracker_id.cjs",
"load_agent_output.cjs",
},
}

if deps, ok := dependencyMap[actionName]; ok {
return deps
}
return []string{}
}
68 changes: 17 additions & 51 deletions specs/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,14 @@ Create a custom actions system that:
┌─────────────────────────────────────────────────────────┐
│ actions/ Directory │
│ ┌────────────────────────────────────────────────────┐ │
│ │ setup-safe-inputs/ setup-safe-outputs/ │ │
│ │ ├── action.yml ├── action.yml │ │
│ │ ├── index.js ├── index.js │ │
│ │ ├── src/ ├── src/ │ │
│ │ │ └── index.js │ └── index.js │ │
│ │ └── README.md └── README.md │ │
│ │ setup/ │ │
│ │ ├── action.yml │ │
│ │ ├── setup.sh │ │
│ │ ├── js/ │ │
│ │ │ └── *.cjs (copied from pkg/workflow/js/) │ │
│ │ ├── sh/ │ │
│ │ │ └── *.sh (source of truth) │ │
│ │ └── README.md │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
```text
Expand Down Expand Up @@ -149,18 +151,6 @@ gh-aw/
│ │ ├── sh/ # Shell scripts (SOURCE OF TRUTH)
│ │ │ └── *.sh # Manually edited shell scripts
│ │ └── README.md # Action-specific docs
│ ├── setup-safe-inputs/ # Safe inputs MCP server setup
│ │ ├── action.yml # Action metadata
│ │ ├── index.js # Bundled output (committed)
│ │ ├── src/ # Source files
│ │ │ └── index.js # Source that references FILES constant
│ │ └── README.md # Action-specific docs
│ └── setup-safe-outputs/ # Safe outputs MCP server setup
│ ├── action.yml # Action metadata
│ ├── index.js # Bundled output (committed)
│ ├── src/ # Source files
│ │ └── index.js # Source that references FILES constant
│ └── README.md # Action-specific docs
├── pkg/
│ ├── cli/
│ │ └── actions_build_command.go # Build system implementation
Expand Down Expand Up @@ -319,31 +309,12 @@ Currently uses manual mapping in `getActionDependencies()`:

```go
func getActionDependencies(actionName string) []string {
dependencyMap := map[string][]string{
"setup-safe-outputs": {
"safe_outputs_mcp_server.cjs",
"safe_outputs_bootstrap.cjs",
"safe_outputs_tools_loader.cjs",
"safe_outputs_config.cjs",
"safe_outputs_handlers.cjs",
"mcp_server_core.cjs",
"mcp_logger.cjs",
"messages.cjs",
},
"setup-safe-inputs": {
"safe_inputs_mcp_server.cjs",
"safe_inputs_bootstrap.cjs",
"safe_inputs_config_loader.cjs",
"safe_inputs_tool_factory.cjs",
"safe_inputs_validation.cjs",
"mcp_server_core.cjs",
"mcp_logger.cjs",
},
}

if deps, ok := dependencyMap[actionName]; ok {
return deps
// For setup, use the dynamic script discovery
// This ensures all .cjs files are included automatically
if actionName == "setup" {
return workflow.GetAllScriptFilenames()
}

return []string{}
}
```text
Expand Down Expand Up @@ -449,15 +420,10 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Setup Safe Inputs
uses: ./actions/setup-safe-inputs
with:
destination: /tmp/safe-inputs

- name: Setup Safe Outputs
uses: ./actions/setup-safe-outputs
- name: Setup Workflow Scripts
uses: ./actions/setup
with:
destination: /tmp/safe-outputs
destination: /tmp/scripts
```text

### Creating a New Action
Expand Down Expand Up @@ -727,7 +693,7 @@ The custom GitHub Actions build system provides a foundation for migrating from
✅ **Go-based build system** reusing workflow bundler infrastructure
✅ **Makefile integration** for action management
✅ **CI validation** ensuring actions stay buildable
✅ **Two initial actions** (setup-safe-inputs, setup-safe-outputs)
✅ **Setup action** for workflow script management
✅ **Comprehensive documentation** for future development

The system is production-ready and extensible, with clear paths for enhancement and migration of existing inline scripts.
Expand Down
Loading