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
32 changes: 32 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: 2

updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
groups:
minor-and-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"
# Workaround for dependabot/dependabot-core#14202: without an explicit
# major group, major updates matching the minor-and-patch pattern are
# silently suppressed. Remove this group when #14202 is fixed to get
# individual (ungrouped) PRs per major bump instead.
major:
patterns:
- "*"
update-types:
- "major"
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci"
include: "scope"
open-pull-requests-limit: 10
cooldown:
default-days: 1
62 changes: 35 additions & 27 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ✅ Check
name: "✅ Check"
on:
push:
branches:
Expand All @@ -15,81 +15,89 @@ concurrency:
cancel-in-progress: true

permissions:
contents: write
checks: write
contents: read

jobs:
lint:
name: 🔬 ESLint
name: "\U0001F52C ESLint"
runs-on: ubuntu-latest
timeout-minutes: 10
if: ${{ !github.event.pull_request.draft || github.event_name == 'push' }}
permissions:
contents: write
checks: write
steps:
- name: 📥 Checkout repo
uses: actions/checkout@v4
- name: "\U0001F4E5 Checkout repo"
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: ⚙️ Setup node
uses: actions/setup-node@v4
- name: "⚙️ Setup node"
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
cache: npm

- name: 📥 Download deps
- name: "\U0001F4E5 Download deps"
run: npm ci

- name: 🔬 Lint
uses: wearerequired/lint-action@v2
- name: "\U0001F52C Lint"
uses: wearerequired/lint-action@548d8a7c4b04d3553d32ed5b6e91eb171e10e7bb # v2
with:
eslint: true
eslint_args: "**/*.{mjs,ts,tsx}"
prettier: true
prettier_args: "--config ./.prettierrc.json \"**/*.{js,json,ts,tsx,css,md,html}\""

test:
name: 🔎 Test
name: "\U0001F50E Test"
runs-on: ubuntu-latest
timeout-minutes: 10
if: ${{ !github.event.pull_request.draft || github.event_name == 'push' }}
steps:
- name: 📥 Checkout repo
uses: actions/checkout@v4
- name: "\U0001F4E5 Checkout repo"
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: ⚙️ Setup node
uses: actions/setup-node@v4
- name: "⚙️ Setup node"
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
cache: npm

- name: 📥 Download deps
- name: "\U0001F4E5 Download deps"
run: npm ci

- name: 🎭 Install Playwright browsers
- name: "\U0001F3AD Install Playwright browsers"
run: npx playwright install chromium chromium-headless-shell

- name: 🔎 Unit Tests
- name: "\U0001F50E Unit Tests"
run: CI=1 npm test -- --run

- name: 🔎 Integration Tests
- name: "\U0001F50E Integration Tests"
run: CI=1 npm run test:integration -- --run


build:
name: 🔨 Build
name: "\U0001F528 Build"
timeout-minutes: 10
runs-on: ubuntu-latest
if: ${{ !github.event.pull_request.draft || github.event_name == 'push' }}
steps:
- name: 📥 Checkout repo
uses: actions/checkout@v4
- name: "\U0001F4E5 Checkout repo"
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: ⚙️ Setup node
uses: actions/setup-node@v4
- name: "⚙️ Setup node"
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
cache: npm

- name: 📥 Download deps
- name: "\U0001F4E5 Download deps"
run: npm ci

- name: 🔨 Build
- name: "\U0001F528 Build"
run: npm run build
32 changes: 32 additions & 0 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Dependabot Auto-Merge (Minor/Patch)

on:
pull_request_target:
types: [opened, synchronize]

permissions:
contents: write
pull-requests: write

jobs:
auto-merge:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]'
steps:
- name: Fetch Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Auto-approve and merge minor/patch github-actions updates
if: >-
steps.metadata.outputs.package-ecosystem == 'github_actions' &&
(steps.metadata.outputs.update-type == 'version-update:semver-minor' ||
steps.metadata.outputs.update-type == 'version-update:semver-patch')
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh pr review "$PR_URL" --approve
gh pr merge "$PR_URL" --auto --merge
144 changes: 144 additions & 0 deletions .github/workflows/dependabot-major-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: Dependabot Major Version Analysis

on:
pull_request_target:
types: [opened]

permissions:
contents: read
pull-requests: write

jobs:
analyze-major:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]'
steps:
- name: Fetch Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Analyze major version bump
if: >-
steps.metadata.outputs.package-ecosystem == 'github_actions' &&
steps.metadata.outputs.update-type == 'version-update:semver-major'
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
env:
DEP_NAME: ${{ steps.metadata.outputs.dependency-names }}
PREV_VERSION: ${{ steps.metadata.outputs.previous-version }}
NEW_VERSION: ${{ steps.metadata.outputs.new-version }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const depName = process.env.DEP_NAME;
const prevVersion = process.env.PREV_VERSION;
const newVersion = process.env.NEW_VERSION;
const parts = depName.split('/');
const owner = parts[0];
const repo = parts[1];
const repoSlug = `${owner}/${repo}`;

let releases = [];
try {
const { data } = await github.rest.repos.listReleases({ owner, repo, per_page: 50 });
releases = data;
} catch (err) {
core.warning(`Could not fetch releases for ${repoSlug}: ${err.message}`);
}

const prevMajor = parseInt(prevVersion.replace(/^v/, ''), 10);
const newMajor = parseInt(newVersion.replace(/^v/, ''), 10);

const relevantReleases = releases.filter(r => {
const major = parseInt(r.tag_name.replace(/^v/, ''), 10);
return major > prevMajor && major <= newMajor;
});

let releaseNotesSummary = '';
let breakingChanges = '';

if (relevantReleases.length === 0) {
releaseNotesSummary = '_No releases found between these versions._';
breakingChanges = `_Unable to determine breaking changes automatically. Please review the [full changelog](https://github.com/${repoSlug}/releases)._`;
} else {
for (const release of relevantReleases.slice(0, 10)) {
const body = release.body || '_No release notes._';
releaseNotesSummary += `### ${release.tag_name}${release.name && release.name !== release.tag_name ? ' — ' + release.name : ''}\n\n`;
releaseNotesSummary += body.substring(0, 2000);
if (body.length > 2000) releaseNotesSummary += '\n\n_...truncated_';
releaseNotesSummary += '\n\n---\n\n';
const lines = body.split('\n');
for (const line of lines) {
if (/breaking|BREAKING|removed|deprecated|incompatible|migration/i.test(line)) {
breakingChanges += `- ${line.trim()}\n`;
}
}
}
}

if (!breakingChanges) {
breakingChanges = '_No explicit breaking changes detected in release notes. Manual review recommended._';
}

let commentBody = `## :warning: Major Version Update — Manual Review Required

| Field | Value |
|-------|-------|
| **Action** | [\`${depName}\`](https://github.com/${repoSlug}) |
| **Previous** | \`v${prevVersion}\` |
| **New** | \`v${newVersion}\` |
| **Type** | Major (\`v${prevMajor}\` → \`v${newMajor}\`) |

### Breaking Changes

${breakingChanges}

### Release Notes (v${prevMajor + 1} → v${newMajor})

${releaseNotesSummary}

### Next Steps

1. Review breaking changes above
2. Check if workflow inputs/outputs changed
3. Verify compatibility with your CI/CD configuration

> Full changelog: https://github.com/${repoSlug}/releases

---
_Generated automatically for Dependabot major version PRs._`.replace(/^ /gm, '');

if (commentBody.length > 64000) {
commentBody = commentBody.substring(0, 63900) + '\n\n_...comment truncated due to size limit._';
}

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: commentBody,
});

try {
const labelsToAdd = ['major-update', 'needs-review'];
for (const label of labelsToAdd) {
try {
await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
} catch {
const colors = { 'major-update': 'B60205', 'needs-review': 'FBCA04' };
await github.rest.issues.createLabel({
owner: context.repo.owner, repo: context.repo.repo,
name: label, color: colors[label] || 'EDEDED',
});
}
}
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: labelsToAdd,
});
} catch (err) {
core.warning(`Could not add labels: ${err.message}`);
}
Loading
Loading