跳到正文
cccskills
免费在 GitHub 公开

javascript-refactoring

Guides the refactoring of large JavaScript files into smaller CommonJS modules within gh-aw. It covers source placement, function exports, tests, and action builds so extracted code remains testable and is included in generated actions.

中文简介正在准备中。当前显示英语简介。

原文查看原文说明

Split large JavaScript files into maintainable modules safely.

集成工具GitHub
查看安装方法

适用场景

  • Splitting a large JavaScript file by responsibility
  • Extracting utilities shared across workflows
  • Adding tests for extracted modules
  • Investigating changes missing from generated actions

包含的文件(1)

  • SKILL.md7.9 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

JavaScript Code Refactoring Guide

Use this guide to split JavaScript into maintainable CommonJS modules in gh-aw without drifting into dead embedding patterns.

Overview

The current gh-aw architecture is action-centric:

  • Shared JS modules live under pkg/workflow/js/*.cjs and actions/setup/js/*.cjs
  • Action source files live under actions/<action-name>/src/
  • Generated action bundles are committed under actions/<action-name>/index.js
  • Shipping is driven by the action build pipeline (make actions-build, gh aw actions-build) and dependency maps such as pkg/cli/actions_build_command.go
  • pkg/workflow/js.go is a stub; it no longer owns the runtime JavaScript shipping path for the main workflows

If you are refactoring a workflow utility, prefer the current action/module architecture over any older //go:embed pattern.

Top-Level Script Pattern

Top-level .cjs scripts executed directly in workflows follow this pattern:

✅ Correct Pattern - Export main, but don't call it:

async function main() {
  // Script logic here
  core.info("Running the script");
}

module.exports = { main };

❌ Incorrect Pattern - Don't call main in the file:

async function main() {
  // Script logic here
  core.info("Running the script");
}

await main(); // ❌ Don't do this!

module.exports = { main };

Why this pattern?

  • The workflow bundler or action build step can wrap the script with await main() at execution time
  • The module stays importable for tests while still being executable in GitHub Actions
  • It makes unit testing easier and preserves a clean module boundary

Step 1: Put the code in the right source tree

Choose the correct location for the module before writing code:

  • Shared workflow utilities: pkg/workflow/js/
  • Action-specific JavaScript: actions/<action-name>/src/ or actions/setup/js/
  • Generated bundle output: actions/<action-name>/index.js

File naming convention:

  • Use snake_case for filenames (for example sanitize_content.cjs, load_agent_output.cjs)
  • Use .cjs for CommonJS modules
  • Keep the name aligned with the responsibility of the module

Example file structure:

// @ts-check
/// <reference types="@actions/github-script" />

/**
 * Brief description of what this module does
 */

/**
 * Function documentation
 * @param {string} input - Description of parameter
 * @returns {string} Description of return value
 */
function myFunction(input) {
  return input;
}

module.exports = {
  myFunction,
};

Key points:

  • Include // @ts-check for TypeScript checking
  • Include /// <reference types="@actions/github-script" /> when the module is used with GitHub Actions scripts
  • Use JSDoc comments for documentation
  • Export functions via module.exports = { ... }
  • Do not import @actions/core or @actions/github directly unless the module is running in an action context that explicitly expects it

Step 2: Add tests next to the module

Create a matching test beside the module using the same base name plus .test.cjs:

Example: pkg/workflow/js/my_module.test.cjs

import { describe, it, expect, beforeEach, vi } from "vitest";

const mockCore = {
  debug: vi.fn(),
  info: vi.fn(),
  warning: vi.fn(),
  error: vi.fn(),
  setFailed: vi.fn(),
  setOutput: vi.fn(),
};

global.core = mockCore;

describe("myFunction", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("handles a normal input", async () => {
    const { myFunction } = await import("./my_module.cjs");
    expect(myFunction("test input")).toBe("expected output");
  });

  it("handles empty input", async () => {
    const { myFunction } = await import("./my_module.cjs");
    expect(myFunction("")).toBe("");
  });
});

Testing guidelines:

  • Use Vitest for test execution
  • Mock core and github globals as needed
  • Use dynamic imports (await import()) to allow module setup at test time
  • Clear mocks in beforeEach
  • Cover success, failure, and edge cases

Run tests:

make test-js

Step 3: Wire the module into the actual build path

Do not add a new //go:embed mapping just to ship a new runtime script. The current repo ships JavaScript through the action-generation/build pipeline.

Use this checklist:

  • Shared utility used by generated actions: update the relevant dependency mapping in pkg/cli/actions_build_command.go
  • Action-specific source file: add the module under actions/<action-name>/src/
  • Generated action bundle: rebuild with make actions-build
  • Shared workflow source for runtime modules: keep it under pkg/workflow/js/ and update the action or workflow definition that consumes it

Example design:

const { myFunction } = require("./my_module.cjs");

async function main() {
  const result = myFunction("some input");
  core.info(`Result: ${result}`);
}

module.exports = { main };

Step 4: Validate the refactor

Run the relevant checks for the area you changed:

make fmt-cjs
make lint-cjs
make test-js
make test-unit
make actions-build

Verification Checklist

Before committing your refactor:

  • New .cjs file created in the correct source directory
  • Matching .test.cjs file created
  • Tests pass with make test-js or the targeted Vitest suite
  • The module is wired through the real action/workflow build path
  • No stale embedding instructions were added for the current action-based JS build flow
  • Local require() statements work correctly in other JS files
  • Code formatted with make fmt-cjs
  • Relevant validation passes with make lint-cjs or make test-unit

Common Patterns

Pattern 1: Shared Utility Module

Files like sanitize_content.cjs or load_agent_output.cjs are best kept under pkg/workflow/js/ or actions/setup/js/ and consumed by other JS modules via require().

Pattern 2: Action-specific file

When the JavaScript belongs to a single action, keep it under actions/<action-name>/src/ and regenerate the output bundle with make actions-build.

Pattern 3: Top-level workflow script

If the script is executed directly in a workflow, export main and omit the direct await main() call. The host build/runtime step handles execution.

Troubleshooting

Issue: changes are not showing up in generated actions

Cause: Action bundle was not rebuilt after editing the source file

Solution:

make actions-build

Issue: tests fail with core is not defined

Cause: Missing global mocks

Solution:

global.core = mockCore;

Issue: the module is only used in one place

Cause: It was added to the wrong layer

Solution: Move it to the action-specific source tree instead of creating a broad workflow-level registry entry.

Test-Coverage Auditing

Do not audit coverage in actions/setup/js/ by matching foo.cjs to foo.test.cjs by basename. That approach overstates untested files because tests here load sources in three other ways:

  • One test file per behavior, not per source: create_discussion_labels.test.cjs and create_discussion_sanitization.test.cjs both cover create_discussion.cjs.
  • Cache-busting dynamic import: parse_copilot_log.test.cjs uses await import("./parse_copilot_log.cjs?" + Date.now()) to get fresh module state per test.
  • readFileSync + eval: collect_ndjson_output.test.cjs reads the script source with fs.readFileSync(scriptPath, "utf8") and runs it with eval(...).

Resolve require, import, and readFileSync targets from each test file (and their transitive requires) before reporting a source file as untested.

References

  • actions/README.md - current action-generation/build workflow
  • pkg/cli/actions_build_command.go - action dependency mapping
  • pkg/workflow/js/*.cjs - existing shared module patterns
  • actions/setup/js/*.cjs - action runtime/source examples

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Coordinate work across AI agents with shared rules for locating team files, recording decisions and their reasons, and requesting help. It also defines who owns revisions after a reviewer rejects an artifact.

中文简介正在准备中。当前显示英语简介。

  • Locate team files across separate working directories
  • Record decisions that affect other agents
  • Request input from another specialist
github/gh-aw54222026年10月19日 更新

Set shared development rules for an agent team: keep specific agent names out of product code, tests, and CI configuration, verify affected tests before finishing, and record lessons learned from mistakes.

中文简介正在准备中。当前显示英语简介。

  • Share development rules across multiple agents
  • Keep team-specific agent names out of code and tests
  • Check affected tests before declaring work complete
github/gh-aw54222026年10月19日 更新

Routes requests to design, create, update, debug, or upgrade GitHub Agentic Workflows to the appropriate instructions. It helps the agent select a workflow-specific procedure and apply any additional rules defined for the repository.

中文简介正在准备中。当前显示英语简介。

  • Designing a new workflow through questions
  • Investigating failed runs and recurring errors
  • Upgrading workflows and addressing deprecations
github/gh-aw54222026年10月19日 更新

Prepare architecture proposals before implementation so the team can agree on a direction. Organize evidence, technical choices, effects on existing work, risks, and the first release’s scope into a document with clear recommendations and decision owners.

中文简介正在准备中。当前显示英语简介。

  • Proposing a major architecture change
  • Replanning milestones after a foundation change
  • Comparing technical options before seeking approval
github/gh-aw54222026年10月19日 更新

Update the gh-aw-firewall version used by gh-aw, rebuild generated files, and review release notes and configuration schemas, which define valid settings. It guides related code and test updates while identifying follow-up work that remains.

中文简介正在准备中。当前显示英语简介。

  • Updating the firewall version used by gh-aw
  • Reviewing release notes for integration changes
  • Checking configuration schema differences
github/gh-aw54222026年10月19日 更新

Review git and gh operations in gh-aw workflows to check credential availability for each repository. Identify missing token handoffs, risky expansions of limited checkouts, and error handling needed where credentials are intentionally unavailable.

中文简介正在准备中。当前显示英语简介。

  • Reviewing git operations after repository checkout
  • Checking tokens for private cross-repository access
  • Reviewing sparse and shallow checkout changes
github/gh-aw54222026年10月19日 更新

查看 github 的全部技能

报告此技能的问题