emdash-github-actions
EmDash Plugin GitHub Actions
This skill helps you set up a comprehensive CI/CD pipeline for EmDash plugins using GitHub Actions. EmDash is a full-stack TypeScript CMS based on Astro, so its plugin ecosystem is entirely TypeScript-based.
What this skill covers
There are several categories of workflows that a healthy EmDash plugin should have. Not every plugin needs all of them — the right mix depends on the plugin's complexity, whether it has a React admin UI, whether it has tests, etc. Your job is to figure out which ones are relevant and set them up.
The workflows fall into these categories:
- Type checking — TypeScript strict mode with emdash peer dependency
- Code quality — ESLint with TypeScript support
- Testing — Vitest or similar TypeScript-native test runner
- Security — npm audit for dependency vulnerabilities
- Deployment — Automated npm publish on tag/release
Read references/workflows.md for the detailed configuration of each workflow, including ready-to-use YAML templates and configuration files.
How to approach a request
Step 1: Understand the plugin
Before writing any workflow files, figure out what you're working with:
- What does the plugin do? Check the
package.jsondescription andsrc/index.tsexports. EmDash plugins typically hook intopage:metadata,page:fragment, content hooks, or provide admin UI. - Does it have a React admin UI? Check for
.tsxfiles oradmin.tsx. If yes, the type-check needs@types/reactand--jsx react-jsx. - Does it have tests? Check for a
tests/or__tests__/directory, or avitest.config.ts. If yes, set up the test workflow. If not, mention that adding tests would be valuable but don't force it. - What are its peer dependencies? Check
package.jsonforpeerDependencies. EmDash plugins always depend onemdashand may depend onreact,astro, etc. - Does it use additional npm dependencies? Check for
dependenciesinpackage.json. If yes, the CI needs annpm installstep. - Is it published to npm? Check if the package name is scoped (e.g.,
@org/emdash-plugin-foo) and whether it has apublishConfig. If yes, the deploy workflow is relevant.
Step 2: Recommend a set of workflows
Based on what you found, recommend which workflows to set up. A good default for most plugins:
- TypeScript type-check (almost always — this is the most valuable check)
- ESLint (if the plugin has more than a handful of files)
- npm audit (cheap security check, almost always worth it)
And conditionally:
- Vitest tests (if tests exist)
- npm publish (if the plugin is published to npm)
Step 3: Create the workflow files
Create each workflow as a separate YAML file in .github/workflows/. Using separate files rather than one monolithic workflow gives clearer feedback in PRs (each check shows independently) and makes it easier to enable/disable individual checks.
Use the templates from references/workflows.md as starting points, but adapt them to the specific plugin. Common adaptations include:
- Adding
@types/reactif the plugin has.tsxfiles - Adding additional peer dependencies that provide types
- Adjusting file paths for the type-check and lint commands
- Configuring the npm publish scope and access level
Step 4: Create supporting config files
Depending on which workflows you set up, you may also need:
tsconfig.json— TypeScript configuration (if not already present)eslint.config.js— ESLint flat config with TypeScript supportvitest.config.ts— Vitest configuration
Step 5: Set up secrets reminder
If you're adding the npm publish workflow, remind the user that they need to configure a repository secret in GitHub:
NPM_TOKEN— Their npm access token with publish permissions
Walk them through: Repository Settings > Secrets and variables > Actions > New repository secret.
For scoped packages (@org/package-name), the token must have access to the organization.
Naming conventions
Use descriptive workflow file names that make it obvious what each one does:
ci.yml— TypeScript type-checking (the primary CI check)lint.yml— ESLinttest.yml— Vitest/test runnersecurity.yml— npm auditpublish.yml— npm publish on release
Important details
Node.js version: Use Node.js 22 as the default. EmDash is built on modern TypeScript and Astro, so there's no need to support older Node versions. Use actions/checkout@v5 and actions/setup-node@v5 (v5 runs on Node.js 24 runners, avoiding the Node.js 20 deprecation).
Peer dependency installation: EmDash plugins declare emdash as a peer dependency. For type-checking in CI, you must explicitly install emdash (and @types/react if the plugin has .tsx files) since peer dependencies aren't auto-installed in a standalone plugin repo.
The --skipLibCheck flag: Use --skipLibCheck when running tsc in CI. EmDash and its transitive dependencies may have internal type issues that aren't relevant to the plugin author. --skipLibCheck skips checking .d.ts files while still fully checking the plugin's own source code.
The find command for file discovery: Don't use shell globs like src/**/*.ts in CI commands — they fail when no files match at a given depth. Use $(find src -name '*.ts' -o -name '*.tsx') instead.
Branch naming: Most EmDash plugin repos use main as the default branch. Always check the actual repo and use the correct branch name in workflow triggers.