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
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"changes": {
"bindings/devup-ui-wasm/package.json": "Patch",
"apps/landing/package.json": "Patch"
"bindings/devup-ui-wasm/package.json": "Patch"
},
"note": "Respect source-order property replacement across conditional spreads in styled rule objects, and document that styled callbacks cannot return runtime class names. No new build errors; existing located Cannot compose errors remain unchanged.",
"date": "2026-10-01T00:00:00.000Z"
Expand Down
3 changes: 1 addition & 2 deletions .changepacks/changepack_log_css_output_edges.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"changes": {
"bindings/devup-ui-wasm/package.json": "Patch",
"apps/landing/package.json": "Patch"
"bindings/devup-ui-wasm/package.json": "Patch"
},
"note": "Preserve unitless legacy vendor numbers, classify vendor time values as milliseconds and emit the Opera vendor prefix correctly; reject nested responsive arrays and known dead unprefixed CSS property names with source-located build errors, while preserving supported experimental CSS, unknown properties and documented shorthands.",
"date": "2026-10-01T00:00:00.000Z"
Expand Down
7 changes: 0 additions & 7 deletions .changepacks/changepack_log_docs_accuracy.json

This file was deleted.

3 changes: 1 addition & 2 deletions .changepacks/changepack_log_docs_breakpoints.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"changes": {
"bindings/devup-ui-wasm/package.json": "Patch",
"apps/landing/package.json": "Patch"
"bindings/devup-ui-wasm/package.json": "Patch"
},
"note": "Typography documents the emitted default breakpoints, and source-backed integration tests keep the public breakpoint lists and range bounds synchronized with the production defaults. No runtime changes or new build errors.",
"date": "2026-10-01T00:00:00.000Z"
Expand Down
95 changes: 95 additions & 0 deletions packages/__tests__/changepack-paths.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import assert from 'node:assert/strict'
import { resolve } from 'node:path'

import { describe, expect, it } from 'bun:test'

const root = resolve(import.meta.dir, '../..')
// Bun's filesystem API avoids the node:fs spies used by the plugin suites.
const config: unknown = await Bun.file(
resolve(root, '.changepacks/config.json'),
).json()
assert(typeof config === 'object' && config !== null && 'ignore' in config)
assert(Array.isArray(config.ignore))

// This is deliberately scoped to the asserted config, not a gitignore parser.
const managedManifests = new Set(
config.ignore.slice(1).flatMap((pattern: unknown) => {
assert(typeof pattern === 'string')
return [
...new Bun.Glob(pattern.slice(1)).scanSync({
cwd: root,
onlyFiles: true,
}),
]
.map((path) => path.replaceAll('\\', '/'))
.filter((path) =>
/^(packages|bindings)\/[^/]+\/package\.json$/.test(path),
)
}),
)

function unmanagedPaths(paths: readonly string[]): string[] {
// Do not normalize log keys: aliases must not silently resolve as canonical keys.
return paths.filter((path) => !managedManifests.has(path)).sort()
}

describe('changepack manifest paths', () => {
it('uses the supported managed-package allowlist when reading current config', () => {
expect(config.ignore).toEqual([
'*',
'!packages/*/*',
'!bindings/*/package.json',
])
})

it.each([
'packages/react/package.json',
'bindings/devup-ui-wasm/package.json',
])('accepts %s when it is an existing managed manifest', (path) => {
const rejected = unmanagedPaths([path])
expect(rejected).toEqual([])
})

it.each([
'apps/landing/package.json',
'package.json',
'benchmark/tailwindcss/package.json',
'packages/__tests__/package.json',
'bindings/__missing_changepack_manifest__/package.json',
'packages/react/src/package.json',
'packages/react/README.md',
'./packages/react/package.json',
'packages//react/package.json',
'packages/react/../react/package.json',
'packages\\react\\package.json',
'Packages/react/package.json',
'packages/react/package.json/',
])('rejects %s when it is unmanaged, missing or noncanonical', (path) => {
const rejected = unmanagedPaths([path])
expect(rejected).toEqual([path])
})

it('resolves every changes key when reading all changepack logs', async () => {
const logs = [
...new Bun.Glob('.changepacks/changepack_log_*.json').scanSync({
cwd: root,
onlyFiles: true,
}),
]
.map((path) => path.replaceAll('\\', '/'))
.sort()
const diagnostics: string[] = []
for (const path of logs) {
const log: unknown = await Bun.file(resolve(root, path)).json()
assert(typeof log === 'object' && log !== null && 'changes' in log, path)
assert(typeof log.changes === 'object' && log.changes !== null, path)
assert(!Array.isArray(log.changes), path)
diagnostics.push(
...unmanagedPaths(Object.keys(log.changes)).map(
(key) => `${path}: ${key}`,
),
)
}
expect(diagnostics.sort()).toEqual([])
})
})
Loading