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
11 changes: 9 additions & 2 deletions docs/contributing/dependency-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,16 @@ Dependency Review is a complement to normal code review. A green dependency-revi
- npm dependencies from the repository root; and
- GitHub Actions referenced by workflows.

Checks run weekly. Compatible minor and patch updates are grouped to reduce pull-request noise. Major updates remain separate so compatibility, migration requirements, security impact, and release impact can be reviewed explicitly.
Both ecosystems are checked **weekly on Mondays in the `Africa/Lagos` timezone** — npm at **08:00** and GitHub Actions at **08:30** — with an **open pull-request limit of 5 each**.

Dependabot pull requests must pass the same CI/security checks as contributor pull requests and remain subject to maintainer review. No auto-merge policy is enabled by this configuration.
Compatible minor and patch updates are grouped to reduce pull-request noise:

- `npm-minor-and-patch` for npm `minor` and `patch` updates;
- `github-actions-minor-and-patch` for GitHub Actions `minor` and `patch` updates.

Major updates are intentionally excluded from these groups and remain **separate** so compatibility, migration requirements, security impact, and release impact can be reviewed explicitly.

Dependabot pull requests must pass the same CI/security checks as contributor pull requests and remain subject to maintainer review. **No auto-merge policy is enabled** by this configuration.

## Updates

Expand Down
96 changes: 96 additions & 0 deletions tests/dependabot-policy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { describe, expect, it } from 'vitest';

const root = join(import.meta.dirname, '..');
const config = readFileSync(join(root, '.github', 'dependabot.yml'), 'utf8');
const policy = readFileSync(
join(root, 'docs', 'contributing', 'dependency-policy.md'),
'utf8',
);

describe('Dependabot grouping policy alignment', () => {
type UpdateBlock = {
ecosystem: string;
body: string;
groupName: string;
};

const configBlocks = config.split(/\n\s*-\s*package-ecosystem:/).slice(1);

const blocks: UpdateBlock[] = configBlocks.map((segment) => {
const lines = segment.split('\n');
const firstLine = lines[0];
const rest = lines.slice(1);
const ecosystem = firstLine?.trim() ?? '';
const body = rest.join('\n');

// Extract group name (npm-minor-and-patch or github-actions-minor-and-patch)
let groupName = '';
if (ecosystem === 'npm') {
if (body.includes('npm-minor-and-patch')) {
groupName = 'npm-minor-and-patch';
}
} else if (ecosystem === 'github-actions') {
if (body.includes('github-actions-minor-and-patch')) {
groupName = 'github-actions-minor-and-patch';
}
}

return {
ecosystem,
body,
groupName,
};
});

it('defines npm and GitHub Actions update policies', () => {
const ecosystems = blocks.map((b) => b.ecosystem);
expect(ecosystems).toContain('npm');
expect(ecosystems).toContain('github-actions');
});

it('uses weekly Monday cadence in Africa/Lagos with documented times and limits', () => {
expect(config).toContain('interval: weekly');
expect(config).toContain('day: monday');
expect(config).toContain('timezone: Africa/Lagos');
expect(config).toContain("time: '08:00'");
expect(config).toContain("time: '08:30'");
expect(config).toContain('open-pull-requests-limit: 5');
});

it('groups minor and patch updates only, isolating major updates', () => {
for (const block of blocks) {
expect(block.body).toMatch(/minor/);
expect(block.body).toMatch(/patch/);
// Major must not appear under update-types (or at all in the context of grouped updates)
expect(block.body).not.toMatch(/- major\b/);
}

// Cross-check: no grouped major updates anywhere in the config
expect(config).not.toMatch(/update-types:\s*[\s\S]*?- major\b/);
});

it('names the expected Dependabot groups', () => {
const groupNames = blocks.map((b) => b.groupName);
expect(groupNames).toContain('npm-minor-and-patch');
expect(groupNames).toContain('github-actions-minor-and-patch');
});

it('does not introduce auto-merge for Dependabot PRs', () => {
expect(config).not.toMatch(/auto-merge|automerge|auto_merge/i);
expect(policy).toMatch(/No auto-merge policy is enabled/i);
});

it('documents the Dependabot policy accurately in the dependency policy', () => {
expect(policy).toContain('npm-minor-and-patch');
expect(policy).toContain('github-actions-minor-and-patch');
expect(policy).toMatch(
/weekly on Mondays in the `Africa\/Lagos` timezone/i,
);
expect(policy).toContain('08:00');
expect(policy).toContain('08:30');
expect(policy).toMatch(/open pull-requests? limit of 5/i);
expect(policy).toMatch(/major updates are intentionally excluded/i);
});
});