Skip to main content

Workflows

Generate GitHub Actions workflow files under .github/workflows/ from the "workflows" array in nova.config.json.

The generator reads each entry, validates triggers and targets, substitutes variables from the template metadata, validates the output YAML, and writes the result to disk.

Why Use This Command?

  • Bootstraps a full set of CI/CD workflows without writing YAML by hand.
  • Publishes one project to multiple destinations (npm, GitHub Packages, Docker, hosting) from a single build, instead of each destination running its own pipeline from scratch.
  • Serializes dependent publishes (e.g., preset waits for its core dependency to be on the registry) via needs on publish targets.
  • Keeps workflow definitions consistent across Nova-managed repositories.

Requirements

  • Node.js runtime — Use any Node.js LTS release.
  • Project root — Run the command from the directory containing the top-level package.json.
  • Configured workflows — The "workflows" array must exist in nova.config.json. Use nova utility initialize to configure it interactively.

Usage

Options

FlagDescription
-d, --dry-runPreview the target file path without writing anything to disk.
-r, --replace-fileOverwrite the existing file instead of creating a .nova-backup copy.

Config-Driven Workflow Entries

Each entry in the "workflows" array maps to one output file. An entry contains:

FieldRequiredDescription
templateYesThe name of a bundled workflow template (see Available Templates).
suffixYesA label appended to the output filename and workflow name. Must be unique within the same template.
triggersYesAn array of trigger names (see Available Triggers). Use an empty array to omit triggers.
depends-onNoAn array of workflow references in {template}-{suffix} format. Required when using workflow-run-* triggers.
scopesNoAn array of workspace paths (keys from workspaces) to include in the check / build step filter.
targetsNoAn array of publish destinations for the publish template. See Target Fields.
settingsNoKey-value pairs that remap secret / variable names or supply values for literal template variables.

Target Fields

Each entry in the targets array pins one publish destination to a workspace.

FieldRequiredDescription
typeYesOne of the 8 target types (see Available Target Types).
workingDirYesPath to the workspace that owns the target (e.g., "./packages/nova").
needsNoWorking directories of other same-type targets that must finish publishing before this one starts.

Config Examples

Publish a single package to npm:

{
  "template": "publish",
  "suffix": "project",
  "triggers": ["release"],
  "scopes": ["./packages/core"],
  "targets": [
    {
      "type": "npm",
      "workingDir": "./packages/core"
    }
  ],
  "settings": {
    "NPM_TOKEN": "NPM_TOKEN",
    "ROOT_WORKING_DIR": "./"
  }
}

Serialize dependent publishes with needs:

{
  "template": "publish",
  "suffix": "project",
  "triggers": ["release"],
  "scopes": [
    "./packages/core",
    "./packages/preset"
  ],
  "targets": [
    {
      "type": "npm",
      "workingDir": "./packages/core"
    },
    {
      "type": "npm",
      "workingDir": "./packages/preset",
      "needs": ["./packages/core"]
    }
  ],
  "settings": {
    "NPM_TOKEN": "NPM_TOKEN",
    "ROOT_WORKING_DIR": "./"
  }
}

The preset target waits for core to finish publishing before it starts, so consumers that pull [email protected] can always resolve its declared dependency on [email protected].

Publish to multiple destinations from one build:

{
  "template": "publish",
  "suffix": "project",
  "triggers": ["release"],
  "scopes": [
    "./packages/sdk",
    "./apps/docs"
  ],
  "targets": [
    {
      "type": "npm",
      "workingDir": "./packages/sdk"
    },
    {
      "type": "github-packages",
      "workingDir": "./packages/sdk"
    },
    {
      "type": "cloudflare-pages-docusaurus",
      "workingDir": "./apps/docs"
    }
  ],
  "settings": {
    "CLOUDFLARE_ACCOUNT_ID": "CLOUDFLARE_ACCOUNT_ID",
    "CLOUDFLARE_API_TOKEN": "CLOUDFLARE_API_TOKEN",
    "CLOUDFLARE_PROJECT_NAME": "CLOUDFLARE_PROJECT_NAME",
    "NPM_TOKEN": "NPM_TOKEN",
    "ROOT_WORKING_DIR": "./"
  }
}

Each target becomes its own publish job. Jobs run in parallel off a shared build job, except where needs declares an explicit ordering.

Available Templates

The generator currently bundles three templates, each with its own trigger set.

TemplateDescriptionNotes
publishBuild once and publish to one or more targetsRequires targets. Each target declares its own secret / variable setup.
lock-inactive-issuesLock stale issues and pull requestsNo manual setup needed (uses automatic GITHUB_TOKEN). Pick a cadence via triggers.
check-sponsor-gated-issuesGate issues by GitHub sponsor statusRequires PERSONAL_ACCESS_TOKEN secret plus several literal settings.

Available Target Types

The publish template supports the following type values for each entry in targets. Each type has its own template under targets/ and declares its own secrets and variables.

TypeDescription
npmPublish a package to npm
github-packagesPublish a package to GitHub Packages
docker-hubPublish a Docker image to Docker Hub
ghcrPublish a Docker image to GitHub Container Registry
cloudflare-pages-docusaurusDeploy a Docusaurus site to Cloudflare Pages
github-pages-docusaurusDeploy a Docusaurus site to GitHub Pages
aws-amplify-nextjsDeploy a Next.js app to AWS Amplify
vercel-nextjsDeploy a Next.js app to Vercel

Available Triggers

Each template supports a specific set of triggers. The generator reads the available triggers from the template's triggers/ folder.

TemplateTriggers
publishrelease, workflow-run-success, workflow-run-failure, workflow-run-any
lock-inactive-issuesschedule-daily, schedule-weekly, schedule-monthly
check-sponsor-gated-issuesissues, issue-comment
TriggerRequires depends-on
releaseNo
schedule-dailyNo
schedule-weeklyNo
schedule-monthlyNo
issuesNo
issue-commentNo
workflow-run-successYes
workflow-run-failureYes
workflow-run-anyYes

All templates also include workflow_dispatch (manual trigger with dry-run option) automatically.

Variable Formats

Each template declares variables with one of three formats. The format determines how the value is substituted into the generated YAML:

FormatSubstitution behavior
secretProduces ${{ secrets.NAME }} in the output. If a setting is provided, the secret reference uses the setting value as the name instead.
varProduces ${{ vars.NAME }} in the output. If a setting is provided, the variable reference uses the setting value as the name instead.
literalReplaces the placeholder with the exact string from settings. All literal variables must have a corresponding setting or the entry is skipped.

Output Filename Convention

Generated files are written to .github/workflows/ with the naming pattern:

nova-{template}-{suffix}.yml

Examples:

  • nova-lock-inactive-issues-project.yml
  • nova-publish-project.yml
  • nova-check-sponsor-gated-issues-project.yml

How It Works

Reading Config

The generator loads nova.config.json and reads the "workflows" array. If the array is missing or empty, the generator exits with no changes.

Validation

Before generating each file, the generator checks:

  1. The template name matches a known bundled template.
  2. The template directory and base file exist on disk.
  3. Each trigger in triggers has a corresponding file in the template's triggers/ folder.
  4. When a trigger requires depends-on, the config entry provides it and the referenced workflow exists.
  5. Circular depends-on references are detected and rejected.
  6. Each target's type has a matching target template.
  7. Each target's workingDir exists as a workspace key.
  8. Each entry in a target's needs array references a same-type target defined in the same workflow.
  9. All literal-format variables have a corresponding entry in settings.
  10. No two entries produce the same output filename.

If any check fails, the entry is skipped with an error message.

File Generation

Each valid entry produces one YAML file under .github/workflows/. The generator composes the template's base.yml with the resolved triggers and targets, substitutes variable placeholders based on the template metadata and the entry's settings, and emits needs: ["build", ...] on each target job that declares dependencies.

If the target file already exists, a .nova-backup copy is created unless --replace-file is set.

Orphan Cleanup

After generation, the generator scans .github/workflows/ for existing nova-*.yml files that are not in the current config. These orphaned files are backed up (renamed with a .nova-backup timestamp) or deleted when --replace-file is set.

Setup Instructions

After all files are generated, the generator prints a summary of secrets and variables that need to be configured on GitHub. This covers every non-automatic secret and var format variable across all generated workflows.