Skip to content

Contributing and migration workflow ​

Day-to-day contribution ​

  1. Branch from main using branch naming.
  2. Make changes; keep docs and .github/labeler.yml in sync when you add projects or change conventions.
  3. Open a pull request; CI runs monorepo lint and nx affected build and tests (see CI/CD). Use a Conventional Commits title.
  4. After merge, releases are driven by tags, not by committing build artifacts to main.

PR title (Conventional Commits) ​

Use type(optional-scope): description. The scope is optional. Mark breaking changes with ! in the PR title, for example feat!: description or feat(scope)!: description. The squash commit uses only the PR title, so a BREAKING CHANGE: footer in the PR description will not be included. See the Conventional Commits specification.

TypeMeaningExample
featAdd a featurefeat(theme): add event filters
fixFix a bugfix(plugin): handle empty response
perfImprove performanceperf(blocks): reduce render work
revertRevert a changerevert: remove event filters
docsDocumentation onlydocs: clarify local setup
styleFormatting or style changestyle: normalize spacing
refactorRestructure code without behavior changerefactor(plugin): simplify query setup
testAdd or update teststest(theme): cover event filters
buildBuild system or dependency changebuild: update build tooling
ciCI configuration or scriptsci: validate pull request titles
choreMaintenance taskschore: update development dependencies

When opening a PR:

  • Treat the prefilled title as a draft and edit it to match the change.
  • Fix the title on the PR page; do not add a commit just to change it.
  • Once the repository admin configures squash merging to use the PR title, that title becomes the commit message on main. The title check does not block merging until Validate PR title is required in the main branch ruleset or protection settings (see CI/CD).

After checking out a branch ​

Build output (dist/ and similar artifacts) is not committed to the repository. Whenever you check out or pull a branch—especially when reviewing a pull request—refresh dependencies and rebuild so your local environment matches that branch:

bash
pnpm install
pnpm build

Run both from the monorepo root. To rebuild only the project you are reviewing:

bash
pnpm install
npx nx run <project-name>:build

Adding a new repository (greenfield) ​

Prefer the generators so structure matches standards:

bash
npx nx generate monorepo:theme
# or
npx nx generate monorepo:plugin
pnpm install

Then implement features, add docs/index.md for the docs site, and register paths in .github/labeler.yml if needed.

Importing an existing repository (history preservation) ​

Warning: Import and history rewriting steps must not be run against the original standalone repository. Work from a new clone of the monorepo or a dedicated migration branch.

Preconditions ​

Coordinate with maintainers before large imports:

  • Development freeze on the source repo (optional but recommended) so the import has a clear cut-over commit.
  • Final release from the legacy repo if consumers need a last semver from the old remote.
  • Access to create tags and run CI in this monorepo.

1. Import Git history (nx import) ​

bash
npx nx import <git-repository-url> <destination-path>

Example:

bash
npx nx import https://github.com/bcgov/design-system-wordpress-theme themes/design-system-wordpress-theme

Complete the wizard; history for the subtree is preserved in the monorepo.

2. Align structure with monorepo standards ​

After import, the tree often needs to match generator output:

  1. Temporarily rename the imported directory (for example prefix with _) so generators can write a fresh folder.
  2. Run the appropriate generator (monorepo:theme or monorepo:plugin) with the same slug as the imported project.
  3. Copy generated files into the renamed import directory, overwriting where appropriate (some hosts block bulk overwrites in the IDE; use the filesystem if needed).
  4. Remove the empty generator-only directory; restore the imported directory name.
  5. Use Git to revert any overwrite that should stay legacy (for example real version numbers instead of generator defaults).
  6. Reconcile runtime dependencies before testing:
    • For a child theme, make the parent consistent across style.css (Template:), .wp-env.json, and project.json (build dependency and implicitDependencies).
    • If templates use blocks from a monorepo plugin, add the plugin to .wp-env.json, activate it in the environment lifecycle scripts, and add the plugin to implicitDependencies.
    • Compare generated browser-test configuration with existing suites. Prefer shared helpers from @bcew-monorepo/e2e when applicable, then regenerate and verify screenshot baselines.
  7. Remove redundant per-repo files that now belong at the root (see Shared tooling):
    • .github/ (per-package workflows)
    • dist/ / build output
    • Duplicate .gitignore, .markdownlint*, CODEOWNERS if superseded by monorepo policy
    • composer.lock at package level when the monorepo standard is root + package resolution (follow team practice). A local Composer install may recreate a package-level lockfile; do not commit it.
  8. Commit the migration; run pnpm composer-install, npx nx run <project>:build, and pnpm lint.

Tag namespacing after migration ​

First release from the monorepo must use the Nx project name and tag format:

text
<nx-project-name>/v<semver>

Legacy tags from the old repository are not reused as-is; document mapping for consumers if needed.

Branch naming ​

Use documented conventions (feature/…, fix/…, chore/…, etc.) so reviewers and automation stay consistent.

Checklist (migration) ​

After migration: cut over and archive ​

Once the checklist above is done in the monorepo, retire the standalone GitHub repo. Do not keep developing there.

  1. Update the standalone README — short notice that the project moved, with a link to the monorepo path (and this docs site if useful).
  2. Archive the standalone repo on GitHub (do not delete it).

Archiving makes the repo read-only (no new issues, PRs, or pushes). You do not need separate steps to close PRs, lock branches, or migrate issues.

How to archive ​

On the standalone repository:

  1. Settings → scroll to Danger Zone.
  2. Archive this repository → confirm.

History, old releases, and tags stay available for reference. Prefer archive over delete.

After migration: renaming ​

Import often keeps the legacy folder name. Changing that name (and CSS/JS/PHP that only live in code) is a separate cutover. It is not the temporary _ prefix in Align structure with monorepo standards.

Follow Renaming a plugin or theme: local test, then blog_gov_bc_ca on your branch before the PR.