Skip to main content

javascript-refactoring

Split large JavaScript files into maintainable modules safely.

소스 정보

저장소
github/gh-aw
최근 소스 활동
2026년 9월 1일 03:21
감지된 SKILL.md 언어
영어
스타
5,200
포크
564

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
javascript-refactoring
description
Split large JavaScript files into maintainable modules safely.
# 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:** ```javascript async function main() { // Script logic here core.info("Running the script"); } module.exports = { main }; ``` **❌ Incorrect Pattern - Don't call main in the file:** ```javascript 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:** ```javascript // @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` ```javascript 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:** ```bash 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:** ```javascript 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: ```bash 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:** ```bash make actions-build ``` ### Issue: tests fail with `core is not defined` **Cause:** Missing global mocks **Solution:** ```javascript 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. ## 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
GitHub에서 보기