Skip to content
5 changes: 5 additions & 0 deletions .changeset/patch-copilot-session-id-compatibility.md

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

3 changes: 3 additions & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,9 @@ const TmpGhAwDirSlash = TmpGhAwDir + "/"
// TmpGhAwAgentDir is the agent working directory in the /tmp/gh-aw tree.
const TmpGhAwAgentDir = TmpGhAwDir + "/agent/"

// AwInfoPath is the runtime metadata file updated by engine harnesses.
const AwInfoPath = TmpGhAwDir + "/aw_info.json"

// TmpGhAwAssetsDir is the directory the upload_assets job downloads the
// safe-outputs assets artifact into. It is the single source of truth shared by
// the download step (path:) and the upload_assets.cjs consumer script, so the
Expand Down
4 changes: 4 additions & 0 deletions pkg/constants/version_constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const DefaultClaudeCodeVersion Version = "2.1.296"
// - /models does not silently fail on PATs (check that model listing works with PAT auth)
const DefaultCopilotVersion Version = "1.0.96"

// CopilotSessionIDMinVersion is the minimum Copilot CLI version that supports
// the exact session selector injected by the model-verification harness.
const CopilotSessionIDMinVersion Version = "1.0.35"

// DefaultCopilotSDKVersion is the default version of the @github/copilot-sdk package.
const DefaultCopilotSDKVersion Version = "1.0.16"

Expand Down
3 changes: 3 additions & 0 deletions pkg/workflow/awf_command_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ func cloudHypervisorAllowWriteHostMkdirTarget(guestPath string) (hostPath string
if guestPath == cloudHypervisorWorkspaceWritePath {
return "", false
}
if guestPath == constants.AwInfoPath {
return "", false
}
if rel, ok := strings.CutPrefix(guestPath, cloudHypervisorWorkspaceWritePath+"/"); ok {
return "${GITHUB_WORKSPACE}/" + rel, true
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/workflow/cloud_hypervisor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ func TestCloudHypervisorAWFCommandEmitsAwfHomeMkdirBeforeInvocation(t *testing.T
// /workspace already exists (checked out by actions/checkout) and must not be mkdir'd.
assert.NotContains(t, command, `mkdir -p "${GITHUB_WORKSPACE}"`+"\n")
assert.Contains(t, command, `mkdir -p "${GITHUB_WORKSPACE}/.awf-home" "/tmp/gh-aw/agent"`)
assert.NotContains(t, command, constants.AwInfoPath)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Covered in c2443410: the test includes constants.AwInfoPath, checks it is absent only from the mkdir script, and confirms it remains in the generated AWF configuration. Confirmed again after merging main in 1fc08e9.

assert.Contains(t, command, `if GH_AW_GIT_EXCLUDE="$(git -C "${GITHUB_WORKSPACE}" rev-parse --path-format=absolute --git-path info/exclude 2>/dev/null)"; then`)
assert.Contains(t, command, `if ! grep -qxF -- '/.awf-home/' "$GH_AW_GIT_EXCLUDE"`)

Expand Down Expand Up @@ -356,7 +357,7 @@ func TestCloudHypervisorAWFConfigJSON(t *testing.T) {
assert.NotContains(t, jsonStr, "awmg-cli-proxy")
assert.Contains(t, jsonStr, `"agentTimeout":60`)
assert.Contains(t, jsonStr, `"cloudHypervisor":{"previewEnabled":true,"mountPolicy":"workspace-and-tool-cache","vcpuCount":2,"memoryMib":4096}`)
assert.Contains(t, jsonStr, `"allowWrite":["/tmp/gh-aw/agent","/tmp/gh-aw/sandbox/agent/logs","/workspace","/workspace/.awf-home"]`)
assert.Contains(t, jsonStr, `"allowWrite":["/tmp/gh-aw/agent","/tmp/gh-aw/sandbox/agent/logs","/tmp/gh-aw/aw_info.json","/workspace","/workspace/.awf-home"]`)
}

func TestCloudHypervisorValidationArcDindIncompatible(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/workflow/copilot_engine_installation.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (e *CopilotEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHu
// the rootless location to ${RUNNER_TEMP}/gh-aw/bin/copilot where AWF expects it.
rootless := isArcDindTopology(workflowData)
compiledVersion := workflowData.CompiledVersion
npmSteps := generateCopilotInstallerSteps(copilotVersion, "Install GitHub Copilot CLI", rootless, compiledVersion, "", getNVXGuestLibc(workflowData))
npmSteps := generateCopilotInstallerSteps(copilotVersion, "Install GitHub Copilot CLI", rootless, compiledVersion, string(constants.CopilotSessionIDMinVersion), getNVXGuestLibc(workflowData))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Covered in c2443410: the effective minimum is passed to cached CLI selection even for latest, with regression coverage for obsolete-only and compatible caches. The regression passes after merging main in 1fc08e9.

if len(inlineDriverWriteStep) > 0 {
npmSteps = append(npmSteps, inlineDriverWriteStep)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/workflow/copilot_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func generateCopilotInstallerSteps(version, stepName string, rootless bool, comp
" env:",
" GH_HOST: github.com",
}
stepLines = appendCopilotInstallerVersionEnv(stepLines, "", "", guestLibc)
stepLines = appendCopilotInstallerVersionEnv(stepLines, "", copilotMinVersion, guestLibc)

return []GitHubActionStep{GitHubActionStep(stepLines)}
}
Expand Down
15 changes: 9 additions & 6 deletions pkg/workflow/copilot_installer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ func TestCopilotEngineWithVersion(t *testing.T) {
if !strings.Contains(installStep, `install_copilot_cli.sh" `+customVersion) {
t.Errorf("Expected user-specified version %q in install step, got:\n%s", customVersion, installStep)
}
if !strings.Contains(installStep, "GH_AW_COPILOT_MIN_VERSION: "+string(constants.CopilotSessionIDMinVersion)) {
t.Errorf("Expected Copilot CLI feature minimum in install step, got:\n%s", installStep)
}
if strings.Contains(installStep, `install_copilot_cli.sh" `+string(constants.DefaultCopilotVersion)) {
t.Errorf("Expected user-specified version, not default version, in install step:\n%s", installStep)
}
Expand Down Expand Up @@ -110,7 +113,7 @@ func TestCopilotEngineWithoutVersion(t *testing.T) {
}
}

func TestCopilotEngineWithWebSearchWithoutPinnedVersionOmitsMinVersion(t *testing.T) {
func TestCopilotEngineWithWebSearchWithoutPinnedVersionIncludesMinVersion(t *testing.T) {
engine := NewCopilotEngine()
workflowData := &WorkflowData{
Name: "test-workflow",
Expand All @@ -135,15 +138,15 @@ func TestCopilotEngineWithWebSearchWithoutPinnedVersionOmitsMinVersion(t *testin
if installStep == "" {
t.Fatal("Could not find install step with install_copilot_cli.sh")
}
if strings.Contains(installStep, "GH_AW_COPILOT_MIN_VERSION:") {
t.Errorf("Unavailable web-search must not impose a minimum CLI version, got:\n%s", installStep)
if !strings.Contains(installStep, "GH_AW_COPILOT_MIN_VERSION: "+string(constants.CopilotSessionIDMinVersion)) {
t.Errorf("Copilot model verification requires the session selector minimum, got:\n%s", installStep)
}
if strings.Contains(installStep, "install_copilot_cli.sh\" "+string(constants.DefaultCopilotVersion)) {
t.Errorf("Install step must not embed an explicit version arg when engine.version is unset; got:\n%s", installStep)
}
}

func TestCopilotEngineWithWebSearchExpressionVersionOmitsMinVersion(t *testing.T) {
func TestCopilotEngineWithWebSearchExpressionVersionIncludesMinVersion(t *testing.T) {
engine := NewCopilotEngine()
expressionVersion := "${{ inputs.engine-version }}"
workflowData := &WorkflowData{
Expand Down Expand Up @@ -174,8 +177,8 @@ func TestCopilotEngineWithWebSearchExpressionVersionOmitsMinVersion(t *testing.T
if !strings.Contains(installStep, "ENGINE_VERSION: "+expressionVersion) {
t.Errorf("Expected ENGINE_VERSION env var with expression, got:\n%s", installStep)
}
if strings.Contains(installStep, "GH_AW_COPILOT_MIN_VERSION:") {
t.Errorf("Unavailable web-search must not impose a minimum CLI version, got:\n%s", installStep)
if !strings.Contains(installStep, "GH_AW_COPILOT_MIN_VERSION: "+string(constants.CopilotSessionIDMinVersion)) {
t.Errorf("Copilot model verification requires the session selector minimum, got:\n%s", installStep)
}
if !strings.Contains(installStep, `"${ENGINE_VERSION}"`) {
t.Errorf(`Expected install step to pass resolved ENGINE_VERSION to script, got:\n%s`, installStep)
Expand Down
1 change: 1 addition & 0 deletions pkg/workflow/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ func ensureDefaultAgentWritePath(sandboxConfig *SandboxConfig, engineConfig *Eng
addAllowWritePathIfMissing(sandboxConfig.Agent.Config.Filesystem, defaultAgentWorkspaceWritePath)
if engineConfig != nil && engineConfig.ID == string(constants.CopilotEngine) {
addAllowWritePathIfMissing(sandboxConfig.Agent.Config.Filesystem, defaultAgentLogsWritePath)
addAllowWritePathIfMissing(sandboxConfig.Agent.Config.Filesystem, constants.AwInfoPath)
}
if engineConfig != nil && engineConfig.ID == string(constants.CodexEngine) {
// Codex writes runtime state under CODEX_HOME.
Expand Down
2 changes: 1 addition & 1 deletion pkg/workflow/sandbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func TestApplySandboxDefaults(t *testing.T) {
},
engine: &EngineConfig{ID: "copilot"},
expectDefaultWritePath: true,
expectedAllowWrite: []string{defaultAgentWorkspaceWritePath, defaultAgentLogsWritePath, cloudHypervisorWorkspaceWritePath, cloudHypervisorAwfHomeWritePath},
expectedAllowWrite: []string{defaultAgentWorkspaceWritePath, defaultAgentLogsWritePath, constants.AwInfoPath, cloudHypervisorWorkspaceWritePath, cloudHypervisorAwfHomeWritePath},
expected: &SandboxConfig{
Agent: &AgentSandboxConfig{
Type: SandboxTypeAWF,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ jobs:
env:
GH_HOST: github.com
GH_AW_COMPILED_VERSION: dev
GH_AW_COPILOT_MIN_VERSION: 1.0.35
- name: Install AWF binary
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" vAWF_VERSION --rootless
- name: Determine automatic lockdown mode for GitHub MCP Server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ jobs:
env:
GH_HOST: github.com
GH_AW_COMPILED_VERSION: dev
GH_AW_COPILOT_MIN_VERSION: 1.0.35
- name: Install AWF binary
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" vAWF_VERSION --rootless
- name: Determine automatic lockdown mode for GitHub MCP Server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ jobs:
env:
GH_HOST: github.com
GH_AW_COMPILED_VERSION: dev
GH_AW_COPILOT_MIN_VERSION: 1.0.35
- name: Install AWF binary
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" vAWF_VERSION --rootless
- name: Install Playwright CLI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ jobs:
env:
GH_HOST: github.com
GH_AW_COMPILED_VERSION: dev
GH_AW_COPILOT_MIN_VERSION: 1.0.35
- name: Install AWF binary
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" vAWF_VERSION --rootless
- name: Install Playwright CLI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ jobs:
env:
GH_HOST: github.com
GH_AW_COMPILED_VERSION: dev
GH_AW_COPILOT_MIN_VERSION: 1.0.35
- name: Install AWF binary
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" vAWF_VERSION --rootless
- name: Determine automatic lockdown mode for GitHub MCP Server
Expand Down
Loading