Skip to content

Add ecosystem domains for R, Julia, OCaml, Bazel, Lua#18405

Merged
Mossaka merged 2 commits intomainfrom
add-v6-ecosystem-domains
Feb 25, 2026
Merged

Add ecosystem domains for R, Julia, OCaml, Bazel, Lua#18405
Mossaka merged 2 commits intomainfrom
add-v6-ecosystem-domains

Conversation

@Mossaka
Copy link
Collaborator

@Mossaka Mossaka commented Feb 25, 2026

Summary

  • Adds package registry domains for 5 new language ecosystems
  • Discovered during v6 build-test experiment (gh-aw-build-test)
  • These ecosystems had builds fail or require agent workarounds due to blocked domains

New ecosystems

Ecosystem Domains Impact
bazel releases.bazel.build, mirror.bazel.build, bcr.bazel.build Bazelisk can't download Bazel binary without this
r cloud.r-project.org, cran.r-project.org, cran.rstudio.com R install.packages() completely blocked
julia pkg.julialang.org, julialang.org Julia Pkg.add() needs official registry
ocaml opam.ocaml.org, erratique.ch opam install blocked
lua luarocks.org luarocks install blocked

Test plan

  • Unit tests pass
  • Recompile build-test workflows with new ecosystem identifiers
  • Re-run v6 test workflows to verify domain access

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings February 25, 2026 21:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new ecosystem allowlist domain groups (Bazel, R, Julia, OCaml, Lua) and introduces a new experimental OpenCode engine integration (engine implementation, MCP config rendering/conversion, schema/constants updates, and a smoke-test workflow).

Changes:

  • Add 5 new ecosystem domain categories to ecosystem_domains.json.
  • Add new opencode agentic engine (execution/install steps, MCP config rendering, default domains, registry/schema integration).
  • Add OpenCode MCP gateway conversion script and a new smoke workflow (+ compiled lock workflow).

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pkg/workflow/data/ecosystem_domains.json Adds domain allowlists for bazel/r/julia/ocaml/lua ecosystems.
pkg/workflow/domains.go Adds OpenCode default domains/provider parsing + hooks OpenCode into engine default domain selection.
pkg/workflow/opencode_engine.go Implements OpenCode engine install/execution steps and env handling.
pkg/workflow/opencode_mcp.go Adds OpenCode MCP config rendering via shared JSON renderer.
pkg/workflow/opencode_engine_test.go Unit tests covering OpenCode engine behavior.
pkg/workflow/agentic_engine.go Registers the OpenCode engine in the engine registry.
pkg/parser/schemas/main_workflow_schema.json Allows opencode as a valid engine identifier in schema.
pkg/constants/constants.go Adds OpenCode constants (ports, engine name, defaults, env var names).
pkg/constants/constants_test.go Updates expected engine list to include OpenCode.
pkg/cli/completions_test.go Updates engine-name completion expectations to include OpenCode.
actions/setup/sh/start_mcp_gateway.sh Adds OpenCode gateway-config converter selection branch.
actions/setup/sh/convert_gateway_config_opencode.sh New converter from gateway output to opencode.jsonc MCP config format.
.github/workflows/smoke-opencode.md New OpenCode smoke-test workflow definition.
.github/workflows/smoke-opencode.lock.yml Compiled workflow lock file for the smoke test.
Comments suppressed due to low confidence (1)

pkg/workflow/opencode_engine.go:217

  • The firewall allow-domain set for OpenCode doesn’t take the configured model/provider into account. As a result, using providers outside the hard-coded OpenCodeDefaultDomains (and even though openCodeProviderDomains/GetOpenCodeDefaultDomains exist) will still be blocked by AWF. Consider deriving the default domain list from workflowData.EngineConfig.Model (via GetOpenCodeDefaultDomains) and merging it with network/tool/runtime domains before building the AWF command.
	if firewallEnabled {
		allowedDomains := GetOpenCodeAllowedDomainsWithToolsAndRuntimes(
			workflowData.NetworkPermissions,
			workflowData.Tools,
			workflowData.Runtimes,
		)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 14 to 37
// OpenCodeEngine represents the OpenCode CLI agentic engine.
// OpenCode is a provider-agnostic, open-source AI coding agent that supports
// 75+ models via BYOK (Bring Your Own Key).
type OpenCodeEngine struct {
BaseEngine
}

func NewOpenCodeEngine() *OpenCodeEngine {
return &OpenCodeEngine{
BaseEngine: BaseEngine{
id: "opencode",
displayName: "OpenCode",
description: "OpenCode CLI with headless mode and multi-provider LLM support",
experimental: true, // Start as experimental until smoke tests pass consistently
supportsToolsAllowlist: false, // OpenCode manages its own tool permissions via opencode.jsonc
supportsMaxTurns: false, // No --max-turns flag in opencode run
supportsWebFetch: false, // Has built-in webfetch but not exposed via gh-aw neutral tools yet
supportsWebSearch: false, // Has built-in websearch but not exposed via gh-aw neutral tools yet
supportsFirewall: true, // Supports AWF network sandboxing
supportsPlugins: false,
supportsLLMGateway: true, // Supports LLM gateway on port 10004
},
}
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title/description focuses on adding ecosystem domains, but this change set also introduces a new OpenCode engine (new engine implementation, schema/registry/constants updates, MCP gateway converter, and a smoke workflow). Consider updating the PR title/description (or splitting) so reviewers can correctly scope the review and rollout risk.

Copilot uses AI. Check for mistakes.
Comment on lines 358 to 361
// EnvVarModelAgentOpenCode configures the default OpenCode model for agent execution
EnvVarModelAgentOpenCode = "GH_AW_MODEL_AGENT_OPENCODE"
// EnvVarModelDetectionOpenCode configures the default OpenCode model for detection
EnvVarModelDetectionOpenCode = "GH_AW_MODEL_DETECTION_OPENCODE"
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnvVarModelAgentOpenCode / EnvVarModelDetectionOpenCode are introduced here, but they don’t appear to be wired into workflow generation yet (no references found in pkg/workflow). If these are intended as the default-model fallback mechanism (like the Claude/Codex equivalents), consider updating the relevant engine/compiler code to use them (or omit them until they’re supported) to avoid dead/unused configuration knobs.

Suggested change
// EnvVarModelAgentOpenCode configures the default OpenCode model for agent execution
EnvVarModelAgentOpenCode = "GH_AW_MODEL_AGENT_OPENCODE"
// EnvVarModelDetectionOpenCode configures the default OpenCode model for detection
EnvVarModelDetectionOpenCode = "GH_AW_MODEL_DETECTION_OPENCODE"

Copilot uses AI. Check for mistakes.
Comment on lines 114 to 122
config := EngineInstallConfig{
Secrets: []string{"ANTHROPIC_API_KEY"},
DocsURL: "https://opencode.ai/docs/get-started/",
NpmPackage: "opencode-ai",
Version: string(constants.DefaultOpenCodeVersion),
Name: "OpenCode CLI",
CliName: "opencode",
InstallStepName: "Install OpenCode CLI",
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenCode is described as multi-provider (BYOK), but the installation secret-validation step only allows/validates ANTHROPIC_API_KEY. This will cause OpenCode workflows configured for OpenAI/Google (e.g., engine.env provides OPENAI_API_KEY/GOOGLE_API_KEY and model prefix is openai/google) to fail validation even though those providers are supported. Consider validating a set of alternative provider secrets (e.g., ANTHROPIC_API_KEY/OPENAI_API_KEY/GOOGLE_API_KEY) or selecting which secret(s) to validate based on the configured model/provider.

This issue also appears on line 212 of the same file.

Copilot uses AI. Check for mistakes.
Comment on lines 143 to 170
// extractProviderFromModel extracts the provider name from an OpenCode model string.
// OpenCode uses "provider/model" format (e.g., "anthropic/claude-sonnet-4-20250514").
// Returns the provider prefix, or "anthropic" as default if no slash is found.
func extractProviderFromModel(model string) string {
if model == "" {
return "anthropic"
}
parts := strings.SplitN(model, "/", 2)
if len(parts) < 2 {
return "anthropic"
}
return strings.ToLower(parts[0])
}

// GetOpenCodeDefaultDomains returns the default domains for OpenCode based on the model provider.
// It starts with OpenCodeBaseDefaultDomains and adds the provider-specific API domain.
func GetOpenCodeDefaultDomains(model string) []string {
provider := extractProviderFromModel(model)
domains := make([]string, 0, len(OpenCodeBaseDefaultDomains)+1)
domains = append(domains, OpenCodeBaseDefaultDomains...)

if domain, ok := openCodeProviderDomains[provider]; ok {
domains = append(domains, domain)
}

return domains
}

Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments say OpenCode provider domains are added dynamically via GetOpenCodeDefaultDomains(), but the engineDefaultDomains map uses the static OpenCodeDefaultDomains list and GetOpenCodeDefaultDomains() is currently unused. Either wire model-based provider domain selection into the allow-domain calculation, or simplify by removing the unused dynamic machinery/updating the comments to match actual behavior.

Suggested change
// extractProviderFromModel extracts the provider name from an OpenCode model string.
// OpenCode uses "provider/model" format (e.g., "anthropic/claude-sonnet-4-20250514").
// Returns the provider prefix, or "anthropic" as default if no slash is found.
func extractProviderFromModel(model string) string {
if model == "" {
return "anthropic"
}
parts := strings.SplitN(model, "/", 2)
if len(parts) < 2 {
return "anthropic"
}
return strings.ToLower(parts[0])
}
// GetOpenCodeDefaultDomains returns the default domains for OpenCode based on the model provider.
// It starts with OpenCodeBaseDefaultDomains and adds the provider-specific API domain.
func GetOpenCodeDefaultDomains(model string) []string {
provider := extractProviderFromModel(model)
domains := make([]string, 0, len(OpenCodeBaseDefaultDomains)+1)
domains = append(domains, OpenCodeBaseDefaultDomains...)
if domain, ok := openCodeProviderDomains[provider]; ok {
domains = append(domains, domain)
}
return domains
}

Copilot uses AI. Check for mistakes.
Comment on lines 58 to 178
@@ -73,6 +74,7 @@
"terraform": ["releases.hashicorp.com", "apt.releases.hashicorp.com", "yum.releases.hashicorp.com", "registry.terraform.io"],
"haskell": ["haskell.org", "*.hackage.haskell.org", "get-ghcup.haskell.org", "downloads.haskell.org"],
"kotlin": ["ge.jetbrains.com", "packages.jetbrains.team", "kotlin.bintray.com"],
"julia": ["pkg.julialang.org", "julialang.org", "julialang-s3.julialang.org"],
"java": [
"www.java.com",
"jdk.java.net",
@@ -122,6 +124,7 @@
"download.opensuse.org",
"cdn.redhat.com"
],
"lua": ["luarocks.org", "www.luarocks.org"],
"node": [
"npmjs.org",
"npmjs.com",
@@ -151,6 +154,7 @@
"telemetry.vercel.com"
],
"node-cdns": ["cdn.jsdelivr.net", "data.jsdelivr.com", "code.jquery.com", "cdn.sheetjs.com"],
"ocaml": ["opam.ocaml.org", "ocaml.org", "erratique.ch"],
"perl": ["cpan.org", "www.cpan.org", "metacpan.org", "cpan.metacpan.org"],
"php": ["repo.packagist.org", "packagist.org", "getcomposer.org", "bitbucket.org"],
"playwright": ["playwright.download.prss.microsoft.com", "cdn.playwright.dev"],
@@ -171,6 +175,7 @@
"index.crates.io",
"static.crates.io"
],
"r": ["cloud.r-project.org", "cran.r-project.org", "cran.rstudio.com", "r-project.org"],
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New ecosystem domain categories were added here, but there are no corresponding unit tests asserting that these identifiers expand correctly via GetAllowedDomains (existing tests only cover a subset of categories). Adding a small test case per new ecosystem (bazel/julia/lua/ocaml/r) would help catch JSON formatting mistakes and prevent regressions in domain expansion behavior.

Copilot uses AI. Check for mistakes.
Add package registry domains for 5 new language ecosystems discovered
during v6 build-test experiment:
- bazel: releases.bazel.build, mirror.bazel.build, bcr.bazel.build
- julia: pkg.julialang.org, julialang.org
- lua: luarocks.org
- ocaml: opam.ocaml.org, erratique.ch
- r: cloud.r-project.org, cran.r-project.org, cran.rstudio.com

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mossaka Mossaka force-pushed the add-v6-ecosystem-domains branch from df3e947 to 23e8e17 Compare February 25, 2026 22:32
Add test cases verifying that each new ecosystem identifier correctly
expands to its expected domains via GetAllowedDomains. Also add the
new ecosystems to the category enumeration and uniqueness tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mossaka Mossaka merged commit eca6d0a into main Feb 25, 2026
48 checks passed
@Mossaka Mossaka deleted the add-v6-ecosystem-domains branch February 25, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants