Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,29 @@ build(composer): Update humbug/php-scoper to v0.18.19
chore(actions): Update actions/checkout to v7
```

Allowed: `deps`, `deps-dev`, `wp-plugin`, `wp-theme`, `npm`, `composer`, `actions`. These are emitted by [linchpin/renovatebot-config](https://github.com/linchpin/renovatebot-config); anything else must still be a task key, `NO-TASK`, or an issue number.
Allowed: `deps`, `deps-dev`, `wp-plugin`, `wp-theme`, `npm`, `composer`, `actions`, `wporg`, `linchpin`. These are emitted by [linchpin/renovatebot-config](https://github.com/linchpin/renovatebot-config); anything else must still be a task key, `NO-TASK`, or an issue number.

`build` is the [Angular convention's type for external dependencies](https://www.conventionalcommits.org/en/v1.0.0-beta.4/), and `update` reads better for a WordPress plugin bump β€” both are valid here.

### `wp-plugin` / `wp-theme` as a type instead of a scope

`wp-plugin` and `wp-theme` are also valid **types**, not just scopes:

```
wp-plugin(wporg): Update akismet to v5.3
wp-plugin(linchpin): Update some-plugin to v3.0 - Major
wp-theme(deps): Update twentytwentyfour to v2.0
```

This exists for one reason: [release-please](https://github.com/googleapis/release-please)'s `changelog-sections` groups strictly by commit **type** β€” `changelog-sections[].type` is the only key that schema offers, there is no scope key β€” so a repo that wants WordPress plugin and theme updates in their own changelog section (rather than folded into whatever section `update` or `build` maps to) has no way to get one except by making `wp-plugin`/`wp-theme` the type. `wporg` and `linchpin` are then available as scopes to say which registry the package came from.

Both forms lint cleanly. Use the scope form (`update(wp-plugin):`) unless a repo's `release-please-config.json` specifically defines a dedicated section for the `wp-plugin`/`wp-theme` type β€” [linchpin/renovatebot-config](https://github.com/linchpin/renovatebot-config) is the current example that does.

## Rules

| Rule | Level | Description |
| --- | --- | --- |
| `type-enum` | error | Type must be one of: `add`, `improve`, `build`, `chore`, `ci`, `docs`, `feat`, `feature`, `fix`, `perf`, `refactor`, `remove`, `revert`, `style`, `test`, `update` |
| `type-enum` | error | Type must be one of: `add`, `improve`, `build`, `chore`, `ci`, `docs`, `feat`, `feature`, `fix`, `perf`, `refactor`, `remove`, `revert`, `style`, `test`, `update`, `wp-plugin`, `wp-theme` |
| `subject-case` | warning | Subject must be in sentence-case |

The config also sets a custom `parserPreset.parserOpts.headerPattern` that enforces the scope format.
Expand Down
14 changes: 11 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
'use strict';

const TYPES = ['add', 'improve', 'build', 'chore', 'ci', 'docs', 'feat', 'feature', 'fix', 'perf', 'refactor', 'remove', 'revert', 'style', 'test', 'update'];
// wp-plugin and wp-theme are deliberately in both TYPES and DEP_SCOPES. As a scope
// (`update(wp-plugin): ...`) they keep a WordPress update legible in a mostly automated
// log. As a type (`wp-plugin(wporg): ...`) they let a repo route WordPress plugin and
// theme updates to their own release-please changelog section - `changelog-sections[].type`
// is the only key that schema offers, so a dedicated section is only reachable through
// type. Neither usage is deprecated; pick whichever a repo's release-please-config needs.
const TYPES = ['add', 'improve', 'build', 'chore', 'ci', 'docs', 'feat', 'feature', 'fix', 'perf', 'refactor', 'remove', 'revert', 'style', 'test', 'update', 'wp-plugin', 'wp-theme'];

// Dependency updates have no task behind them, so the scope slot carries the kind of
// dependency instead - which is what the wider ecosystem does too (`build(deps)`,
// `chore(deps-dev)`). wp-plugin and wp-theme keep WordPress updates obvious at a glance
// in a log that is mostly automated. deps-dev precedes deps so the longer one wins.
const DEP_SCOPES = ['deps-dev', 'deps', 'wp-plugin', 'wp-theme', 'npm', 'composer', 'actions'];
// in a log that is mostly automated. wporg and linchpin name a WordPress package's source
// for repos that promote wp-plugin/wp-theme to a type instead, and so need a scope other
// than the type itself. deps-dev precedes deps so the longer one wins.
const DEP_SCOPES = ['deps-dev', 'deps', 'wp-plugin', 'wp-theme', 'npm', 'composer', 'actions', 'wporg', 'linchpin'];

// A ClickUp-style task key, NO-TASK, a GitHub issue number, or a dependency scope.
const SCOPE = new RegExp(`^(?:[A-Z]+-\\d+|NO-TASK|#\\d+|${DEP_SCOPES.join('|')})$`);
Expand Down
27 changes: 27 additions & 0 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,31 @@ describe('@linchpinagency/commitlint-config', () => {
expect(explain(header)).not.toBeNull();
});
});

// wp-plugin and wp-theme double as types, not just scopes, so a repo whose
// release-please-config gives WordPress plugins/themes their own changelog section can
// emit one. release-please groups strictly by type, so this is the only way in.
describe('wp-plugin and wp-theme as types', () => {
const { explain } = config;
const pattern = config.parserPreset.parserOpts.headerPattern;

test.each([
'wp-plugin(wporg): Update akismet to v5.3',
'wp-plugin(linchpin): Update some-plugin to v3.0',
'wp-theme(deps): Update twentytwentyfour to v2.0',
])('accepts %s', (header) => {
expect(explain(header)).toBeNull();
expect(header).toMatch(pattern);
});

test('wporg and linchpin are valid scopes', () => {
expect(explain('wp-plugin(wporg): Update something')).toBeNull();
expect(explain('wp-plugin(linchpin): Update something')).toBeNull();
});

test('the scope form documented above still works alongside the type form', () => {
expect(explain('update(wp-plugin): Update translatepress-multilingual to v3.2.4')).toBeNull();
expect(explain('update(wp-theme): Update ollie-pro to v2.6.1')).toBeNull();
});
});
});