From ddeb37da59f2bfc82b0d3b4ee33ca138d39a1e59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:40:01 +0000 Subject: [PATCH 1/2] Default runs-on for non-reusable custom jobs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../compiler_custom_job_memory_test.go | 41 +++++++++++++++++++ pkg/workflow/compiler_custom_jobs.go | 7 ++++ 2 files changed, 48 insertions(+) diff --git a/pkg/workflow/compiler_custom_job_memory_test.go b/pkg/workflow/compiler_custom_job_memory_test.go index 1023115dbf5..4da7e91addb 100644 --- a/pkg/workflow/compiler_custom_job_memory_test.go +++ b/pkg/workflow/compiler_custom_job_memory_test.go @@ -81,6 +81,47 @@ Reads cache memory and dispatches tasks. assert.NotContains(t, yamlStr, "update_cache_memory:", "update_cache_memory job should not be created without threat detection") } +// TestCustomJobRestoreMemoryUsesDefaultRunsOn verifies that custom restore-memory +// jobs inherit the workflow runner when runs-on is omitted. +func TestCustomJobRestoreMemoryUsesDefaultRunsOn(t *testing.T) { + tmpDir := testutil.TempDir(t, "custom-job-restore-default-runs-on") + + frontmatter := `--- +name: Orchestrator +on: workflow_dispatch +permissions: + contents: read +engine: copilot +strict: false +tools: + cache-memory: true +jobs: + setup: + restore-memory: true + steps: + - name: Verify setup + run: echo "ok" +--- + +# Orchestrator Workflow +` + + testFile := filepath.Join(tmpDir, "test.md") + require.NoError(t, os.WriteFile(testFile, []byte(frontmatter), 0644)) + + compiler := NewCompiler() + require.NoError(t, compiler.CompileWorkflow(testFile)) + + lockFile := filepath.Join(tmpDir, "test.lock.yml") + content, err := os.ReadFile(lockFile) + require.NoError(t, err) + + section := extractJobSection(string(content), "setup") + require.NotEmpty(t, section, "Expected setup job section in lock file") + assert.Contains(t, section, "runs-on: ubuntu-latest", "custom job should inherit default workflow runner when runs-on is omitted") + assert.Contains(t, section, "Restore cache-memory", "restore-memory steps should still be present") +} + // TestCustomJobRestoreMemoryRepoMemory verifies that a custom job with // restore-memory: true gets repo-memory clone steps injected when repo-memory is configured. func TestCustomJobRestoreMemoryRepoMemory(t *testing.T) { diff --git a/pkg/workflow/compiler_custom_jobs.go b/pkg/workflow/compiler_custom_jobs.go index 5ba478129f5..1b0066c06d7 100644 --- a/pkg/workflow/compiler_custom_jobs.go +++ b/pkg/workflow/compiler_custom_jobs.go @@ -477,6 +477,13 @@ func configureCustomReusableWorkflow(job *Job, jobName string, usesStr string, c } func (c *Compiler) configureCustomJobSteps(job *Job, jobName string, configMap map[string]any, data *WorkflowData) error { + if job.RunsOn == "" { + job.RunsOn = data.RunsOn + if job.RunsOn == "" { + job.RunsOn = "runs-on: ubuntu-latest" + } + } + // Add basic steps if specified (only for non-reusable workflow jobs). // `setup-steps` and `pre-steps` stay distinct so setup-steps can remain the // first injected steps in the job, followed by compiler scaffolding, From b33bda2d8c285d77e887d46310ce24c345188710 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 21:04:35 +0000 Subject: [PATCH 2/2] Fix multi-line runs-on indentation for inherited custom job runner Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../compiler_custom_job_memory_test.go | 56 +++++++++++++++++++ pkg/workflow/compiler_custom_jobs.go | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/pkg/workflow/compiler_custom_job_memory_test.go b/pkg/workflow/compiler_custom_job_memory_test.go index 4da7e91addb..de2cdcf9388 100644 --- a/pkg/workflow/compiler_custom_job_memory_test.go +++ b/pkg/workflow/compiler_custom_job_memory_test.go @@ -122,6 +122,62 @@ jobs: assert.Contains(t, section, "Restore cache-memory", "restore-memory steps should still be present") } +// TestCustomJobRestoreMemoryInheritsArrayRunsOn verifies that a custom job with +// restore-memory: true and no explicit runs-on properly inherits a workflow-level +// array/object runs-on, with continuation lines correctly indented. +func TestCustomJobRestoreMemoryInheritsArrayRunsOn(t *testing.T) { + tmpDir := testutil.TempDir(t, "custom-job-restore-array-runs-on") + + frontmatter := `--- +name: Orchestrator +on: workflow_dispatch +permissions: + contents: read +engine: copilot +strict: false +runs-on: + group: ubuntu-runners + labels: [self-hosted] +tools: + cache-memory: true +jobs: + setup: + restore-memory: true + steps: + - name: Verify setup + run: echo "ok" +--- + +# Orchestrator Workflow +` + + testFile := filepath.Join(tmpDir, "test.md") + require.NoError(t, os.WriteFile(testFile, []byte(frontmatter), 0644)) + + compiler := NewCompiler() + require.NoError(t, compiler.CompileWorkflow(testFile)) + + lockFile := filepath.Join(tmpDir, "test.lock.yml") + content, err := os.ReadFile(lockFile) + require.NoError(t, err) + + section := extractJobSection(string(content), "setup") + require.NotEmpty(t, section, "Expected setup job section in lock file") + assert.Contains(t, section, "runs-on:", "custom job should inherit workflow-level runs-on") + assert.Contains(t, section, "group: ubuntu-runners", "custom job should include group from inherited runs-on") + // Verify continuation lines are properly indented (4 spaces) inside the job section. + for line := range strings.SplitSeq(section, "\n") { + if strings.TrimSpace(line) == "" || strings.HasPrefix(strings.TrimSpace(line), "setup:") { + continue + } + if strings.TrimSpace(line) != "" { + assert.True(t, strings.HasPrefix(line, " "), + "all non-empty lines inside job section should be indented with at least 4 spaces, got: %q", line) + } + } + assert.Contains(t, section, "Restore cache-memory", "restore-memory steps should still be present") +} + // TestCustomJobRestoreMemoryRepoMemory verifies that a custom job with // restore-memory: true gets repo-memory clone steps injected when repo-memory is configured. func TestCustomJobRestoreMemoryRepoMemory(t *testing.T) { diff --git a/pkg/workflow/compiler_custom_jobs.go b/pkg/workflow/compiler_custom_jobs.go index 1b0066c06d7..ec80f26e5c5 100644 --- a/pkg/workflow/compiler_custom_jobs.go +++ b/pkg/workflow/compiler_custom_jobs.go @@ -478,7 +478,7 @@ func configureCustomReusableWorkflow(job *Job, jobName string, usesStr string, c func (c *Compiler) configureCustomJobSteps(job *Job, jobName string, configMap map[string]any, data *WorkflowData) error { if job.RunsOn == "" { - job.RunsOn = data.RunsOn + job.RunsOn = c.indentYAMLLines(data.RunsOn, " ") if job.RunsOn == "" { job.RunsOn = "runs-on: ubuntu-latest" }