Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Master -> Next #163

Closed
wants to merge 9 commits into from
5 changes: 0 additions & 5 deletions .changeset/curvy-guests-perform.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/eleven-numbers-leave.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/twelve-snakes-mix.md

This file was deleted.

70 changes: 70 additions & 0 deletions .github/workflows/bundle-size-trusted.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# This is the trusted counterpart of the Bundle size workflow.
# It generates a report and posts a comment on the PR.

name: Bundle size (trusted)

on:
workflow_run:
workflows: [Bundle size]
types:
- completed

permissions:
pull-requests: write

jobs:
print:
name: Print the sizes
runs-on: ubuntu-latest
steps:
- name: Download the sizes
uses: actions/download-artifact@v4
with:
merge-multiple: true
path: '.'
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}

- name: Create the report
id: create-report
uses: actions/github-script@v7
with:
result-encoding: string
script: |
function parseDuOutput(output) {
return Object.fromEntries(output.trim().split('\n').map(line => {
const [size, folderName] = line.split(/\s+/);
const [_packages, packageName, _dist] = folderName.split('/');
return [packageName, parseInt(size, 10)];
}));
}
function formatSize(sizeInBytes) {
if (sizeInBytes < 1000) {
return `${sizeInBytes} B`;
} else {
const sizeInKb = sizeInBytes / 1000;
return `${sizeInKb.toFixed(2)} KB`;
}
}
const fs = require('fs');
const sizes = parseDuOutput(fs.readFileSync(`sizes-${${{ toJson(github.base_ref) }}}.txt`, 'utf8'));
const sizesPR = parseDuOutput(fs.readFileSync(`sizes-${${{ toJson(github.head_ref) }}}.txt`, 'utf8'));
core.summary.addHeading('📊 Package size report', '3');
core.summary.addTable([
['Package', 'Before', 'After'].map((data) => ({ data, header: true })),
...Object.keys(sizes).map((packageName) => {
const size = sizes[packageName];
const sizePR = sizesPR[packageName];
return [packageName, formatSize(size), sizePR === size ? 'No change' : formatSize(sizePR)];
}),
]);
const report = core.summary.stringify();
core.summary.write();
return report;

- name: Post the report to the PR
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
with:
message: ${{ steps.create-report.outputs.result }}
pr-number: ${{ github.event.workflow_run.pull_requests.number }}
comment-tag: bundle-size
44 changes: 44 additions & 0 deletions .github/workflows/bundle-size-untrusted.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# This workflow builds the packages on the base branch and the PR branch, and then records the sizes of the built packages.
# The size comparison is done in a separate workflow because this one can't leave PR comments.

name: Bundle size

on:
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
build:
name: Build on the base branch and the PR branch
strategy:
matrix:
branch:
- ${{ github.base_ref }}
- ${{ github.head_ref }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ matrix.branch }}

- name: Setup
uses: ./.github/actions/setup

- name: Build the packages
run: turbo run build

- name: Collect sizes in bytes
id: sizes
run: du -sb packages/*/dist > sizes-${{ matrix.branch }}.txt

- name: Upload the sizes
uses: actions/upload-artifact@v4
with:
name: sizes-${{ matrix.branch }}
path: sizes-${{ matrix.branch }}.txt
53 changes: 53 additions & 0 deletions .github/workflows/pkg-pr-new.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Publish Approved Pull Requests to pkg.pr.new
on:
pull_request_review:
types: [submitted]

permissions:
contents: read
pull-requests: read

jobs:
check:
# First, trigger a permissions check on the user approving the pull request.
if: github.event.review.state == 'approved'
runs-on: ubuntu-latest
outputs:
has-permissions: ${{ steps.checkPermissions.outputs.result }}
steps:
- name: Check permissions
id: checkPermissions
uses: actions/github-script@v7
with:
result-encoding: string
# The approver must have write access to the repository to trigger the package preview.
script: |
const { data: { permission } } =
await github.rest.repos.getCollaboratorPermissionLevel({
...context.repo,
username: context.actor,
});
return permission === 'write' || permission === 'admin';

publish:
needs: check
# Publish the preview package only if the permissions check passed.
if: needs.check.outputs.has-permissions == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'

- name: Install dependencies
run: pnpm install

- name: Build
run: pnpm exec turbo build

- run: pnpm dlx pkg-pr-new publish './packages/*'
21 changes: 10 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@
"name": "@steiger/root",
"private": true,
"scripts": {
"format": "prettier --write . \"!packages/** !tooling/**\" --cache",
"check-formatting": "prettier --check . \"!packages/** !tooling/**\" --cache",
"format": "prettier --cache --write . \"!packages/**\" \"!tooling/**\"",
"check-formatting": "prettier --cache --check . \"!packages/**\" \"!tooling/**\"",
"check-monorepo": "manypkg check",
"prepare": "husky"
},
"engines": {
"node": ">= 20"
"node": ">= 18"
},
"packageManager": "[email protected]",
"dependencies": {
"@changesets/cli": "^2.27.9",
"@manypkg/cli": "^0.21.4",
"devDependencies": {
"@changesets/cli": "^2.27.10",
"@manypkg/cli": "^0.23.0",
"@steiger/eslint-config": "workspace:*",
"@tsconfig/node-lts": "^20.1.3",
"eslint": "^9.12.0",
"husky": "^9.1.6",
"eslint": "^9.16.0",
"husky": "^9.1.7",
"lint-staged": "^15.2.10",
"prettier": "^3.3.3",
"turbo": "^2.1.3"
"prettier": "^3.4.2",
"turbo": "^2.3.3"
},
"lint-staged": {
"*": "prettier --write --ignore-unknown",
Expand Down
10 changes: 10 additions & 0 deletions packages/pretty-reporter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# @steiger/pretty-reporter

## 0.3.0

### Minor Changes

- 5bc4f60: Make printed diagnostic location more readable

### Patch Changes

- 5c0225f: Prevent links to rule descriptions being broken in some terminals

## 0.2.0

### Minor Changes
Expand Down
15 changes: 8 additions & 7 deletions packages/pretty-reporter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"name": "@steiger/pretty-reporter",
"description": "A reporter that can print Steiger's diagnostics nice and pretty",
"version": "0.2.0",
"version": "0.3.0",
"scripts": {
"example": "tsx example/index.ts",
"lint": "eslint .",
Expand Down Expand Up @@ -31,16 +31,17 @@
"@steiger/eslint-config": "workspace:*",
"@steiger/tsconfig": "workspace:*",
"@steiger/types": "workspace:*",
"@total-typescript/ts-reset": "^0.5.1",
"@types/node": "^20.16.11",
"eslint": "^9.12.0",
"prettier": "^3.3.3",
"tsx": "^4.19.1",
"typescript": "^5.6.3"
"@total-typescript/ts-reset": "^0.6.1",
"@types/node": "^18.11.9",
"eslint": "^9.16.0",
"prettier": "^3.4.2",
"tsx": "^4.19.2",
"typescript": "^5.7.2"
},
"dependencies": {
"chalk": "^5.3.0",
"figures": "^6.1.0",
"picocolors": "^1.1.1",
"terminal-link": "^3.0.0"
}
}
22 changes: 13 additions & 9 deletions packages/pretty-reporter/src/format-single-diagnostic.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { relative } from 'node:path'
import figures from 'figures'
import terminalLink from 'terminal-link'
import chalk from 'chalk'
import pc from 'picocolors'
import type { Diagnostic } from '@steiger/types'

export function formatSingleDiagnostic(d: Diagnostic, cwd: string): string {
const x = d.severity === 'error' ? chalk.red(figures.cross) : chalk.yellow(figures.warning)
const s = chalk.reset(figures.lineDownRight)
const bar = chalk.reset(figures.lineVertical)
const e = chalk.reset(figures.lineUpRight)
const message = chalk.reset(d.message)
const autofixable = d.fixes !== undefined && d.fixes.length > 0 ? chalk.green(`${figures.tick} Auto-fixable`) : null
const location = chalk.gray(formatLocation(d.location, cwd))
const ruleName = chalk.blue(terminalLink(d.ruleName, d.getRuleDescriptionUrl(d.ruleName).toString()))
const x = d.severity === 'error' ? pc.red(figures.cross) : pc.yellow(figures.warning)
const s = pc.reset(figures.lineDownRight)
const bar = pc.reset(figures.lineVertical)
const e = pc.reset(figures.lineUpRight)
const message = pc.reset(d.message)
const autofixable = d.fixes !== undefined && d.fixes.length > 0 ? pc.green(`${figures.tick} Auto-fixable`) : null
const location = pc.underline(formatLocation(d.location, cwd))
const ruleName = pc.blue(
terminalLink(d.ruleName, d.getRuleDescriptionUrl(d.ruleName).toString(), {
fallback: (text, url) => `${pc.reset(text)}: ${pc.blue(url)}`,
}),
)

return `
${s} ${location}
Expand Down
14 changes: 7 additions & 7 deletions packages/pretty-reporter/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import chalk from 'chalk'
import pc from 'picocolors'
import figures from 'figures'
import type { Diagnostic } from '@steiger/types'

Expand All @@ -7,7 +7,7 @@ import { s } from './pluralization.js'

export function formatPretty(diagnostics: Array<Diagnostic>, cwd: string) {
if (diagnostics.length === 0) {
return chalk.green(`${figures.tick} No problems found!`)
return pc.green(`${figures.tick} No problems found!`)
}

const errors = diagnostics.filter((d) => d.severity === 'error')
Expand All @@ -16,17 +16,17 @@ export function formatPretty(diagnostics: Array<Diagnostic>, cwd: string) {
let footer =
'Found ' +
[
errors.length > 0 && chalk.red.bold(`${errors.length} error${s(errors.length)}`),
warnings.length > 0 && chalk.yellow.bold(`${warnings.length} warning${s(warnings.length)}`),
errors.length > 0 && pc.bold(pc.red(`${errors.length} error${s(errors.length)}`)),
warnings.length > 0 && pc.bold(pc.yellow(`${warnings.length} warning${s(warnings.length)}`)),
]
.filter(Boolean)
.join(' and ')

const autofixable = diagnostics.filter((d) => (d.fixes?.length ?? 0) > 0)
if (autofixable.length === diagnostics.length) {
footer += ` (all can be fixed automatically with ${chalk.green.bold('--fix')})`
footer += ` (all can be fixed automatically with ${pc.bold(pc.green('--fix'))})`
} else if (autofixable.length > 0) {
footer += ` (${autofixable.length} can be fixed automatically with ${chalk.green.bold('--fix')})`
footer += ` (${autofixable.length} can be fixed automatically with ${pc.bold(pc.green('--fix'))})`
} else {
footer += ' (none can be fixed automatically)'
}
Expand All @@ -36,7 +36,7 @@ export function formatPretty(diagnostics: Array<Diagnostic>, cwd: string) {
diagnostics.map((d) => formatSingleDiagnostic(d, cwd)).join('\n\n') +
'\n\n' +
// Due to formatting characters, it won't be exactly the size of the footer, that is okay
chalk.gray(figures.line.repeat(footer.length)) +
pc.gray(figures.line.repeat(footer.length)) +
'\n ' +
footer +
'\n'
Expand Down
7 changes: 7 additions & 0 deletions packages/steiger-plugin-fsd/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @feature-sliced/steiger-plugin

## 0.5.4

### Patch Changes

- b55545e: Change the plugin name string to match the npm package name
- 26130b5: Add an exception to the `insignificant-slice` rule when the only usage site is the App layer

## 0.5.3

### Patch Changes
Expand Down
10 changes: 5 additions & 5 deletions packages/steiger-plugin-fsd/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@feature-sliced/steiger-plugin",
"description": "A set of rules to verify correct usage of Feature-Sliced Design",
"version": "0.5.3",
"version": "0.5.4",
"scripts": {
"lint": "eslint .",
"format": "prettier --write . --cache",
Expand Down Expand Up @@ -45,11 +45,11 @@
"@steiger/eslint-config": "workspace:*",
"@steiger/toolkit": "workspace:*",
"@steiger/tsconfig": "workspace:*",
"@total-typescript/ts-reset": "^0.5.1",
"@total-typescript/ts-reset": "^0.6.1",
"@types/lodash-es": "^4.17.12",
"@types/pluralize": "^0.0.33",
"tsup": "^8.3.0",
"typescript": "^5.6.3",
"vitest": "^1.6.0"
"tsup": "^8.3.5",
"typescript": "^5.7.2",
"vitest": "^3.0.0-beta.2"
}
}
2 changes: 1 addition & 1 deletion packages/steiger-plugin-fsd/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import segmentsByPurpose from './segments-by-purpose/index.js'
import sharedLibGrouping from './shared-lib-grouping/index.js'
import typoInLayerName from './typo-in-layer-name/index.js'
import noProcesses from './no-processes/index.js'
import packageJson from '../package.json'
import packageJson from '../package.json' with { type: 'json' }

const rules = [
ambiguousSliceNames,
Expand Down
Loading
Loading