본문으로 건너뛰기
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(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

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 / 1,000자

이 양식은 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-aw5.4천2026년 10월 20일 업데이트

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-aw5.4천2026년 10월 20일 업데이트

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-aw5.4천2026년 10월 20일 업데이트

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-aw5.4천2026년 10월 20일 업데이트

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-aw5.4천2026년 10월 20일 업데이트

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-aw5.4천2026년 10월 20일 업데이트

github의 스킬 모두 보기

이 스킬의 문제 신고