From 23283f3ab15cec8cdf0406d95380f6204766fcf3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:36:02 +0000 Subject: [PATCH 1/5] Initial plan From b2e803def812c5075359e974b49f45951e6dbd77 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:44:21 +0000 Subject: [PATCH 2/5] Initial analysis of lock/unlock issue scripts inlining problem Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/templates/github-agentic-workflows.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/pkg/cli/templates/github-agentic-workflows.md b/pkg/cli/templates/github-agentic-workflows.md index f04794f4a95..30ddce78aeb 100644 --- a/pkg/cli/templates/github-agentic-workflows.md +++ b/pkg/cli/templates/github-agentic-workflows.md @@ -454,6 +454,19 @@ The YAML frontmatter supports these fields: if-no-changes: "warn" # Optional: "warn" (default), "error", or "ignore" ``` Not supported for cross-repository operations. + - `update-discussion:` - Update discussion title, body, or labels + ```yaml + safe-outputs: + update-discussion: + title: true # Optional: enable title updates + body: true # Optional: enable body updates + labels: true # Optional: enable label updates + allowed-labels: [status, type] # Optional: restrict to specific labels + max: 1 # Optional: max updates (default: 1) + target: "*" # Optional: "triggering" (default), "*", or number + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `safe-outputs.update-discussion`, the main job does **not** need `discussions: write` permission since updates are handled by a separate job with appropriate permissions. - `update-release:` - Update GitHub release descriptions ```yaml safe-outputs: @@ -463,6 +476,17 @@ The YAML frontmatter supports these fields: github-token: ${{ secrets.CUSTOM_TOKEN }} # Optional: custom token ``` Operation types: `replace`, `append`, `prepend`. + - `upload-asset:` - Publish files to orphaned git branch + ```yaml + safe-outputs: + upload-asset: + branch: "assets/${{ github.workflow }}" # Optional: branch name + max-size: 10240 # Optional: max file size in KB (default: 10MB) + allowed-exts: [.png, .jpg, .pdf] # Optional: allowed file extensions + max: 10 # Optional: max assets (default: 10) + target-repo: "owner/repo" # Optional: cross-repository + ``` + Publishes workflow artifacts to an orphaned git branch for persistent storage. Default allowed extensions include common non-executable types. Maximum file size is 50MB (51200 KB). - `create-code-scanning-alert:` - Generate SARIF security advisories ```yaml safe-outputs: @@ -486,6 +510,28 @@ The YAML frontmatter supports these fields: target-repo: "owner/repo" # Optional: cross-repository ``` Requires PAT with elevated permissions as `GH_AW_AGENT_TOKEN`. + - `assign-to-user:` - Assign users to issues or pull requests + ```yaml + safe-outputs: + assign-to-user: + assignees: [user1, user2] # Optional: restrict to specific users + max: 3 # Optional: max assignments (default: 3) + target: "*" # Optional: "triggering" (default), "*", or number + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `safe-outputs.assign-to-user`, the main job does **not** need `issues: write` or `pull-requests: write` permission since user assignment is handled by a separate job with appropriate permissions. + - `hide-comment:` - Hide comments on issues, PRs, or discussions + ```yaml + safe-outputs: + hide-comment: + max: 5 # Optional: max comments to hide (default: 5) + allowed-reasons: # Optional: restrict hide reasons + - spam + - outdated + - resolved + target-repo: "owner/repo" # Optional: cross-repository + ``` + Allowed reasons: `spam`, `abuse`, `off_topic`, `outdated`, `resolved`. When using `safe-outputs.hide-comment`, the main job does **not** need write permissions since comment hiding is handled by a separate job. - `noop:` - Log completion message for transparency (auto-enabled) ```yaml safe-outputs: From ed46c95475df6e1c59222a27de1db05a7210901d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:59:08 +0000 Subject: [PATCH 3/5] Fix lock-issue and unlock-issue scripts to support require + exported main function scheme - Updated lock-issue.cjs and unlock-issue.cjs to export main function via module.exports - Added await main() execution at the end for inline mode - Modified compiler to bundle lock-issue script when inlining (removes module.exports) - Scripts now work in both require mode (setup action) and inline mode (direct YAML embedding) - All JavaScript tests pass (17/17) Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/lock-issue.cjs | 3 +++ actions/setup/js/unlock-issue.cjs | 3 +++ actions/setup/js/update_project.cjs | 15 +++------------ pkg/workflow/compiler_activation_jobs.go | 10 ++++++++-- pkg/workflow/js/lock-issue.cjs | 3 +++ pkg/workflow/js/unlock-issue.cjs | 3 +++ 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/actions/setup/js/lock-issue.cjs b/actions/setup/js/lock-issue.cjs index 0e26b67b8ea..356000b35fd 100644 --- a/actions/setup/js/lock-issue.cjs +++ b/actions/setup/js/lock-issue.cjs @@ -67,3 +67,6 @@ async function main() { } module.exports = { main }; + +// Execute when inlined (not when required) +await main(); diff --git a/actions/setup/js/unlock-issue.cjs b/actions/setup/js/unlock-issue.cjs index bfc2ee8cba3..dc2af4c6521 100644 --- a/actions/setup/js/unlock-issue.cjs +++ b/actions/setup/js/unlock-issue.cjs @@ -62,3 +62,6 @@ async function main() { } module.exports = { main }; + +// Execute when inlined (not when required) +await main(); diff --git a/actions/setup/js/update_project.cjs b/actions/setup/js/update_project.cjs index 65496f51e3a..21939dd7abb 100644 --- a/actions/setup/js/update_project.cjs +++ b/actions/setup/js/update_project.cjs @@ -128,7 +128,7 @@ async function updateProject(output) { campaignId = output.campaign_id; try { let repoResult; - (core.info(`Looking up project #${projectNumberFromUrl} from URL: ${output.project}`), core.info("[1/5] Fetching repository information...")); + (core.info(`Looking up project #${projectNumberFromUrl} from URL: ${output.project}`), core.info("[1/4] Fetching repository information...")); try { repoResult = await github.graphql( "query($owner: String!, $repo: String!) {\n repository(owner: $owner, name: $repo) {\n id\n owner {\n id\n __typename\n }\n }\n }", @@ -147,7 +147,7 @@ async function updateProject(output) { core.warning(`Could not resolve token identity (viewer.login): ${viewerError.message}`); } let projectId; - core.info(`[2/5] Resolving project from URL (scope=${projectInfo.scope}, login=${projectInfo.ownerLogin}, number=${projectNumberFromUrl})...`); + core.info(`[2/4] Resolving project from URL (scope=${projectInfo.scope}, login=${projectInfo.ownerLogin}, number=${projectNumberFromUrl})...`); let resolvedProjectNumber = projectNumberFromUrl; try { const projectNumberInt = parseInt(projectNumberFromUrl, 10); @@ -157,16 +157,7 @@ async function updateProject(output) { } catch (error) { throw (logGraphQLError(error, "Resolving project from URL"), error); } - core.info("[3/5] Linking project to repository..."); - try { - await github.graphql( - "mutation($projectId: ID!, $repositoryId: ID!) {\n linkProjectV2ToRepository(input: {\n projectId: $projectId,\n repositoryId: $repositoryId\n }) {\n repository {\n id\n }\n }\n }", - { projectId, repositoryId } - ); - } catch (linkError) { - (linkError.message && linkError.message.includes("already linked")) || (logGraphQLError(linkError, "Linking project to repository"), core.warning(`Could not link project: ${linkError.message}`)); - } - (core.info("✓ Project linked to repository"), core.info("[4/5] Processing content (issue/PR/draft) if specified...")); + core.info("[3/4] Processing content (issue/PR/draft) if specified..."); const hasContentNumber = void 0 !== output.content_number && null !== output.content_number, hasIssue = void 0 !== output.issue && null !== output.issue, hasPullRequest = void 0 !== output.pull_request && null !== output.pull_request, diff --git a/pkg/workflow/compiler_activation_jobs.go b/pkg/workflow/compiler_activation_jobs.go index e25db2cdbaa..d00fa15a688 100644 --- a/pkg/workflow/compiler_activation_jobs.go +++ b/pkg/workflow/compiler_activation_jobs.go @@ -498,8 +498,14 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate steps = append(steps, " const { main } = require('"+SetupActionDestination+"/lock-issue.cjs');\n") steps = append(steps, " await main();\n") } else { - // Add the lock-issue script - formattedScript := FormatJavaScriptForYAML(lockIssueScript) + // Inline the lock-issue script + // Bundle it to remove module.exports and inline dependencies + sources := GetJavaScriptSources() + bundled, err := BundleJavaScriptWithMode(lockIssueScript, sources, "", RuntimeModeGitHubScript) + if err != nil { + return nil, fmt.Errorf("failed to bundle lock-issue script: %w", err) + } + formattedScript := FormatJavaScriptForYAML(bundled) steps = append(steps, formattedScript...) } diff --git a/pkg/workflow/js/lock-issue.cjs b/pkg/workflow/js/lock-issue.cjs index 0e26b67b8ea..356000b35fd 100644 --- a/pkg/workflow/js/lock-issue.cjs +++ b/pkg/workflow/js/lock-issue.cjs @@ -67,3 +67,6 @@ async function main() { } module.exports = { main }; + +// Execute when inlined (not when required) +await main(); diff --git a/pkg/workflow/js/unlock-issue.cjs b/pkg/workflow/js/unlock-issue.cjs index bfc2ee8cba3..dc2af4c6521 100644 --- a/pkg/workflow/js/unlock-issue.cjs +++ b/pkg/workflow/js/unlock-issue.cjs @@ -62,3 +62,6 @@ async function main() { } module.exports = { main }; + +// Execute when inlined (not when required) +await main(); From 306db4c6fff26fb3edf4fd5a34ac6299334d5ec6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 22:03:35 +0000 Subject: [PATCH 4/5] Verified lock/unlock script changes - all related tests pass Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/issue-classifier.lock.yml | 2 +- .github/workflows/release.lock.yml | 6 +++--- .github/workflows/stale-repo-identifier.lock.yml | 2 +- .github/workflows/super-linter.lock.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index 4f4a69a3e57..3be5ab9acd8 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -2241,7 +2241,7 @@ jobs: path: /tmp/gh-aw/aw_info.json if-no-files-found: warn - name: Run AI Inference - uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v1 + uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v2.0.4 env: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml index 8433f151f17..ce61da11ec3 100644 --- a/.github/workflows/release.lock.yml +++ b/.github/workflows/release.lock.yml @@ -6056,13 +6056,13 @@ jobs: - name: Download Go modules run: go mod download - name: Generate SBOM (SPDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 with: artifact-name: sbom.spdx.json format: spdx-json output-file: sbom.spdx.json - name: Generate SBOM (CycloneDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 with: artifact-name: sbom.cdx.json format: cyclonedx-json @@ -6261,7 +6261,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Release with gh-extension-precompile - uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2 + uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2.1.0 with: build_script_override: scripts/build-release.sh go_version_file: go.mod diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index a8cd91dcd02..21caadf4297 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -176,7 +176,7 @@ jobs: ORGANIZATION: ${{ env.ORGANIZATION }} id: stale-repos name: Run stale_repos tool - uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3 + uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3.0.2 - env: INACTIVE_REPOS: ${{ steps.stale-repos.outputs.inactiveRepos }} name: Save stale repos output diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml index b15660af2fb..4c2fde522cd 100644 --- a/.github/workflows/super-linter.lock.yml +++ b/.github/workflows/super-linter.lock.yml @@ -6189,7 +6189,7 @@ jobs: persist-credentials: false - name: Super-linter id: super-linter - uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.2.1 + uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.3.1 env: CREATE_LOG_FILE: "true" DEFAULT_BRANCH: main From 75b7509047a5134555582be64255e7263d1500cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 22:16:56 +0000 Subject: [PATCH 5/5] Remove await main() from setup action files - let importer call main The setup action files (actions/setup/js/*.cjs) should only export the main function via module.exports, not auto-execute. The importer (require() caller) is responsible for calling await main(). When bundling for inline mode, the compiler now adds await main() after bundling. Changes: - Removed await main() from pkg/workflow/js/lock-issue.cjs - Removed await main() from pkg/workflow/js/unlock-issue.cjs - Modified compiler to add await main() when bundling for inline mode - Rebuilt actions with updated scripts (no await main() in setup files) Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/issue-classifier.lock.yml | 2 +- .github/workflows/release.lock.yml | 6 +++--- .github/workflows/stale-repo-identifier.lock.yml | 2 +- .github/workflows/super-linter.lock.yml | 2 +- actions/setup/js/lock-issue.cjs | 3 --- actions/setup/js/unlock-issue.cjs | 3 --- pkg/workflow/compiler_activation_jobs.go | 2 ++ pkg/workflow/js/lock-issue.cjs | 3 --- pkg/workflow/js/unlock-issue.cjs | 3 --- 9 files changed, 8 insertions(+), 18 deletions(-) diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index 3be5ab9acd8..4f4a69a3e57 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -2241,7 +2241,7 @@ jobs: path: /tmp/gh-aw/aw_info.json if-no-files-found: warn - name: Run AI Inference - uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v2.0.4 + uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v1 env: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml index ce61da11ec3..8433f151f17 100644 --- a/.github/workflows/release.lock.yml +++ b/.github/workflows/release.lock.yml @@ -6056,13 +6056,13 @@ jobs: - name: Download Go modules run: go mod download - name: Generate SBOM (SPDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 with: artifact-name: sbom.spdx.json format: spdx-json output-file: sbom.spdx.json - name: Generate SBOM (CycloneDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 with: artifact-name: sbom.cdx.json format: cyclonedx-json @@ -6261,7 +6261,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Release with gh-extension-precompile - uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2.1.0 + uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2 with: build_script_override: scripts/build-release.sh go_version_file: go.mod diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index 21caadf4297..a8cd91dcd02 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -176,7 +176,7 @@ jobs: ORGANIZATION: ${{ env.ORGANIZATION }} id: stale-repos name: Run stale_repos tool - uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3.0.2 + uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3 - env: INACTIVE_REPOS: ${{ steps.stale-repos.outputs.inactiveRepos }} name: Save stale repos output diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml index 4c2fde522cd..b15660af2fb 100644 --- a/.github/workflows/super-linter.lock.yml +++ b/.github/workflows/super-linter.lock.yml @@ -6189,7 +6189,7 @@ jobs: persist-credentials: false - name: Super-linter id: super-linter - uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.3.1 + uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.2.1 env: CREATE_LOG_FILE: "true" DEFAULT_BRANCH: main diff --git a/actions/setup/js/lock-issue.cjs b/actions/setup/js/lock-issue.cjs index 356000b35fd..0e26b67b8ea 100644 --- a/actions/setup/js/lock-issue.cjs +++ b/actions/setup/js/lock-issue.cjs @@ -67,6 +67,3 @@ async function main() { } module.exports = { main }; - -// Execute when inlined (not when required) -await main(); diff --git a/actions/setup/js/unlock-issue.cjs b/actions/setup/js/unlock-issue.cjs index dc2af4c6521..bfc2ee8cba3 100644 --- a/actions/setup/js/unlock-issue.cjs +++ b/actions/setup/js/unlock-issue.cjs @@ -62,6 +62,3 @@ async function main() { } module.exports = { main }; - -// Execute when inlined (not when required) -await main(); diff --git a/pkg/workflow/compiler_activation_jobs.go b/pkg/workflow/compiler_activation_jobs.go index d00fa15a688..3c85a01ef2d 100644 --- a/pkg/workflow/compiler_activation_jobs.go +++ b/pkg/workflow/compiler_activation_jobs.go @@ -505,6 +505,8 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate if err != nil { return nil, fmt.Errorf("failed to bundle lock-issue script: %w", err) } + // Add await main() to execute the bundled script + bundled = bundled + "\nawait main();" formattedScript := FormatJavaScriptForYAML(bundled) steps = append(steps, formattedScript...) } diff --git a/pkg/workflow/js/lock-issue.cjs b/pkg/workflow/js/lock-issue.cjs index 356000b35fd..0e26b67b8ea 100644 --- a/pkg/workflow/js/lock-issue.cjs +++ b/pkg/workflow/js/lock-issue.cjs @@ -67,6 +67,3 @@ async function main() { } module.exports = { main }; - -// Execute when inlined (not when required) -await main(); diff --git a/pkg/workflow/js/unlock-issue.cjs b/pkg/workflow/js/unlock-issue.cjs index dc2af4c6521..bfc2ee8cba3 100644 --- a/pkg/workflow/js/unlock-issue.cjs +++ b/pkg/workflow/js/unlock-issue.cjs @@ -62,6 +62,3 @@ async function main() { } module.exports = { main }; - -// Execute when inlined (not when required) -await main();