-
Notifications
You must be signed in to change notification settings - Fork 5
Add migration manifest tooling for downstream projects #984
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
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
8928ce9
docs: add migration automation design spec
f4-lex bff7911
docs: clarify how SCAN step identifies essencium-origin files
f4-lex 1f2f45f
docs: add migration automation implementation plan
f4-lex 51f291a
chore: add migration manifest for v9.4.5 (accessibility and CVE fixes)
f4-lex 7b1eb31
chore: add migration manifest for v9.5.0 (React Compiler + Next.js 16)
f4-lex b55d623
feat: add /author-migration skill for release manifest generation
f4-lex 10e25ce
chore: remove spec and plan docs from repository
f4-lex 6ed441b
refactor: move author-migration skill to .claude/skills/
f4-lex 1e06e26
docs: add CLAUDE.md with project purpose and structure
f4-lex 6c01275
docs: remove version numbers from CLAUDE.md tech stack
f4-lex 6cd962f
chore: add migration manifests for v6.0.0, v6.1.0, v6.1.1
f4-lex d596459
chore: add migration manifests for v7.0.0 through v7.3.0
f4-lex c552082
chore: add migration manifests for v7.4.0 through v7.10.0
f4-lex 846b568
chore: add migration manifests for v8.1.0 through v9.4.4
f4-lex 53b61ef
fix: correct manifest schema violations in v6.0.0 through v7.3.0
f4-lex b4b69bd
fix: correct manifest schema violations in v7.4.0 through v9.4.0
f4-lex 1938fc0
fix: remaining schema violations in v7.4.0 and v7.8.0 manifests
f4-lex 72b0df5
chore: add migration manifest for v8.0.0
f4-lex 165b89c
fix: address code review feedback on migration tooling
f4-lex File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,221 @@ | ||
| --- | ||
| name: author-migration | ||
| description: "Generate a migration manifest (YAML) for a new essencium-frontend release. Use when preparing a release to document app-level changes for downstream projects." | ||
| argument-hint: "[version]" | ||
| --- | ||
|
|
||
| # Author Migration Manifest | ||
|
|
||
| Generate a migration manifest that documents all app-level changes between two releases of essencium-frontend. The manifest helps downstream projects understand what changed and how to migrate. | ||
|
|
||
| ## Workflow | ||
|
|
||
| ### Step 1: Determine versions | ||
|
|
||
| 1. If a version argument was provided, use it as the **target version**. Otherwise, read the `version` field from `packages/app/package.json`. | ||
| 2. Find the **previous release tag** by running: | ||
| ```bash | ||
| git tag --list 'essencium-app-v*' --sort=-v:refname | ||
| ``` | ||
| - If the target version already has a tag, pick it as current and the next entry as previous. | ||
| - If the target version does not have a tag yet, use `HEAD` as the current ref and the first entry in the tag list as the previous tag. | ||
| 3. Confirm both versions with the user before proceeding. Display: | ||
| - Previous version / tag | ||
| - Target version / ref (tag or HEAD) | ||
|
|
||
| ### Step 2: Diff the app package | ||
|
|
||
| Run these commands to collect the raw change data: | ||
|
|
||
| ```bash | ||
| # Full diff of the app package between the two refs | ||
| git diff <previous-tag>..<current-ref> -- packages/app/ | ||
|
|
||
| # Commit log with PR references | ||
| git log --oneline --grep='#' <previous-tag>..<current-ref> -- packages/app/ | ||
|
|
||
| # Also get the full log for context | ||
| git log --oneline <previous-tag>..<current-ref> -- packages/app/ | ||
|
|
||
| # List newly added files | ||
| git diff --diff-filter=A --name-only <previous-tag>..<current-ref> -- packages/app/ | ||
|
|
||
| # List deleted files | ||
| git diff --diff-filter=D --name-only <previous-tag>..<current-ref> -- packages/app/ | ||
|
|
||
| # List modified files | ||
| git diff --diff-filter=M --name-only <previous-tag>..<current-ref> -- packages/app/ | ||
| ``` | ||
|
|
||
| Extract PR numbers from commit messages (look for patterns like `#123`, `pull/123`, or full GitHub URLs) and construct links in the format: | ||
| `https://github.com/Frachtwerk/essencium-frontend/pull/NNN` | ||
|
|
||
| ### Step 3: Classify changes | ||
|
|
||
| Categorize every change into one of 7 types. Process them in this order: | ||
|
|
||
| #### 3a. `dependency_migration` — Dependency version changes | ||
|
|
||
| Compare `packages/app/package.json` between the two refs to find dependency changes: | ||
|
|
||
| ```bash | ||
| git diff <previous-tag>..<current-ref> -- packages/app/package.json | ||
| ``` | ||
|
|
||
| For each changed dependency: | ||
| - Determine old and new version numbers | ||
| - **Major version bumps** (e.g., 2.x -> 3.x): set `scope: project_wide` — downstream code using that library may need changes | ||
| - **Minor/patch bumps** (e.g., 2.1 -> 2.3): set `scope: package` — just bumping the version is sufficient | ||
| - Exception: if a minor bump introduces known breaking behavior, use `scope: project_wide` and explain in `notes` | ||
| - Set `reference` to the library's changelog or releases page | ||
| - Write a concise `notes` describing the impact | ||
|
|
||
| #### 3b. `infrastructure` — Config/build tool changes | ||
|
|
||
| Check for modifications to these config files: | ||
| - `next.config.js` / `next.config.mjs` | ||
| - `postcss.config.cjs` / `postcss.config.mjs` | ||
| - `tsconfig.json` / `tsconfig.base.json` | ||
| - `eslint.config.mjs` / `.eslintrc.json` | ||
| - `tailwind.config.*` | ||
| - `vitest.config.*` | ||
| - `playwright.config.*` | ||
| - `Dockerfile`, `docker-compose.*` | ||
|
|
||
| Each infrastructure entry should describe what changed and why, list affected files with their action (modified/added), and include a PR link if available. | ||
|
|
||
| #### 3c. `translation` — Locale key changes | ||
|
|
||
| Check `packages/app/public/locales/` for changes: | ||
|
|
||
| ```bash | ||
| git diff <previous-tag>..<current-ref> -- packages/app/public/locales/ | ||
| ``` | ||
|
|
||
| For each locale file changed: | ||
| - Diff the JSON keys to identify `keys_added`, `keys_removed`, and `keys_changed` | ||
| - A key is "changed" if its value was modified but the key still exists | ||
| - Group all locale changes into a single entry per logical change (e.g., if `de` and `en` both got the same new key, that is one entry) | ||
| - List affected locales in the `locales` array | ||
|
|
||
| #### 3d. `env_variable` — Environment variable changes | ||
|
|
||
| Check `.env*` files for changes: | ||
|
|
||
| ```bash | ||
| git diff <previous-tag>..<current-ref> -- packages/app/.env* | ||
| ``` | ||
|
|
||
| Document each added, removed, or changed variable with its name, whether it is required, and optionally a default value (from `.env.example` or the `.env` file in the diff). The `default` field is recommended wherever a sensible default exists; omit it when the value is project-specific. | ||
|
|
||
| #### 3e. `new_file` — Newly added files | ||
|
|
||
| From the `--diff-filter=A` output, create an entry for each new file. Describe the file's purpose by reading its content. Include PR links where possible. | ||
|
|
||
| #### 3f. `file_removal` — Deleted files | ||
|
|
||
| From the `--diff-filter=D` output, create an entry for each deleted file. Explain why it was removed and what replaces it (check the commit message and surrounding changes for context). | ||
|
|
||
| #### 3g. `file_tracking` — All other modified files | ||
|
|
||
| All remaining modified files that were not already classified above go here. Group related files into a single entry when they are part of the same PR or feature. Describe what changed and why. | ||
|
|
||
| ### Step 4: Generate the manifest YAML | ||
|
|
||
| Save the manifest to `packages/app/manifests/<version>.yaml`. | ||
|
|
||
| Before writing, review existing manifests in `packages/app/manifests/` as format examples (especially `9.4.5.yaml` for a small release and `9.5.0.yaml` for a large release). | ||
|
|
||
| The manifest must follow this exact schema: | ||
|
|
||
| ```yaml | ||
| # Top-level fields (all required) | ||
| version: "X.Y.Z" # The version being released | ||
| from: "X.Y.Z" # The previous version | ||
| date: "YYYY-MM-DD" # Today's date | ||
|
|
||
| changes: # Array of change entries | ||
|
|
||
| # ── 1. dependency_migration — library version bumps ────────────────── | ||
| - type: dependency_migration | ||
| package: "package-name" | ||
| from: "old-version" | ||
| to: "new-version" | ||
| scope: project_wide | package # project_wide if API changes, package if just bump | ||
| reference: "url-to-changelog" | ||
| notes: "description of impact" | ||
|
|
||
| # ── 2. infrastructure — config/build tool changes ──────────────────── | ||
| - type: infrastructure | ||
| description: "what changed" | ||
| files: | ||
| - path: "relative/to/app/root" | ||
| action: modified | added | ||
| pr: "https://github.com/Frachtwerk/essencium-frontend/pull/NNN" # optional | ||
| notes: "additional context" # optional | ||
|
|
||
| # ── 3. file_tracking — modified existing files ─────────────────────── | ||
| - type: file_tracking | ||
| description: "what changed and why" | ||
| files: | ||
| - path: "relative/to/app/root" | ||
| action: modified | ||
| pr: "https://github.com/Frachtwerk/essencium-frontend/pull/NNN" # optional | ||
|
|
||
| # ── 4. new_file — newly added files ───────────────────────────────── | ||
| - type: new_file | ||
| path: "relative/to/app/root" | ||
| description: "purpose of the file" | ||
| pr: "https://github.com/Frachtwerk/essencium-frontend/pull/NNN" # optional | ||
|
|
||
| # ── 5. file_removal — deleted files ────────────────────────────────── | ||
| - type: file_removal | ||
| path: "relative/to/app/root" | ||
| description: "why it was removed and what replaces it" | ||
| pr: "https://github.com/Frachtwerk/essencium-frontend/pull/NNN" # optional | ||
|
|
||
| # ── 6. translation — locale key changes ────────────────────────────── | ||
| - type: translation | ||
| description: "what translations changed" | ||
| locales: ["de", "en"] | ||
| keys_added: ["dotted.key.path"] | ||
| keys_removed: ["dotted.key.path"] | ||
| keys_changed: ["dotted.key.path"] | ||
|
|
||
| # ── 7. env_variable — new/changed environment variables ────────────── | ||
| - type: env_variable | ||
| description: "what variables changed" | ||
| variables: | ||
| - name: "VARIABLE_NAME" | ||
| required: true | false | ||
| default: "optional-default-value" # optional — if present, the migration plugin uses this as the initial value | ||
| ``` | ||
|
|
||
| #### Key rules for the manifest | ||
|
|
||
| - **File paths are ALWAYS relative to the app package root** — use `src/...` not `packages/app/src/...`. Strip the `packages/app/` prefix from all paths. | ||
| - **PR links** should be included wherever a PR exists. Omit only for changes that span multiple PRs or were direct pushes without a PR. | ||
| - **`scope: project_wide`** on dependency_migration means downstream code using that library may need changes. **`scope: package`** means just bumping the version is sufficient. | ||
| - **Group related changes** — if multiple files were changed in the same PR/feature, put them in a single `file_tracking` entry with multiple files. | ||
| - **Order changes** by type: infrastructure first, then dependency_migration (major/project_wide before minor/package), then new_file, file_removal, file_tracking, translation, env_variable. | ||
| - **Use comments** as section separators in the YAML (see existing manifests for style). | ||
|
|
||
| ### Step 5: Validate the YAML | ||
|
|
||
| After writing the file, verify it is valid YAML: | ||
|
|
||
| ```bash | ||
| python3 -c "import yaml; yaml.safe_load(open('packages/app/manifests/<version>.yaml')); print('YAML is valid')" | ||
| ``` | ||
|
|
||
| If validation fails, fix the syntax errors and re-validate. | ||
|
|
||
| ### Step 6: Present for review | ||
|
|
||
| Display the complete manifest to the user. Ask them to: | ||
| 1. Review each entry for accuracy | ||
| 2. Confirm dependency scopes are correct | ||
| 3. Check that no changes were missed | ||
| 4. Verify PR links are correct | ||
|
|
||
| Only commit the manifest after the user confirms it is ready. |
|
PhilKsr marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # Essencium Frontend | ||
|
|
||
| Monorepo for the Essencium frontend framework. Provides a component library, shared types, and a Next.js boilerplate that downstream projects scaffold via [create-essencium-app](https://github.com/Frachtwerk/create-essencium-app) and then customize. | ||
|
|
||
| ## Packages | ||
|
|
||
| | Package | Published | Purpose | | ||
| |---------|-----------|---------| | ||
| | `packages/app` | No (private) | Next.js boilerplate — copied by downstream projects as their starting point | | ||
| | `packages/lib` | `@frachtwerk/essencium-lib` | Component library (React, Mantine, Tailwind) | | ||
| | `packages/types` | `@frachtwerk/essencium-types` | Shared TypeScript types and Zod schemas | | ||
| | `packages/eslint-config` | `@frachtwerk/eslint-config-essencium` | Shared ESLint config | | ||
| | `packages/prettier-config` | `@frachtwerk/prettier-config-essencium` | Shared Prettier config | | ||
| | `packages/docs` | No (private) | Documentation site (Nextra) | | ||
|
|
||
| ## Downstream projects | ||
|
|
||
| Multiple projects are built on top of this repo. They install `essencium-lib` and `essencium-types` as npm dependencies, and their codebase started as a copy of `packages/app` which they then customized (new pages, modified components, different config, custom API hooks). | ||
|
|
||
| When this repo releases a new version, downstream projects need to migrate. Migration manifests in `packages/app/manifests/` describe what changed per release. The `/author-migration` skill (in `.claude/skills/`) helps generate these manifests. A separate [migration plugin](https://github.com/Frachtwerk/essencium-frontend-migration-plugin) helps downstream projects apply the changes. | ||
|
|
||
| ## Release tags | ||
|
|
||
| Release tags follow the pattern `essencium-app-vX.Y.Z` (e.g., `essencium-app-v9.5.0`). | ||
|
|
||
| ## Commands | ||
|
|
||
| - `pnpm build` — Build all packages | ||
| - `pnpm dev` — Run app + lib in dev mode with hot reload | ||
| - `pnpm lint` — ESLint across all packages | ||
| - `pnpm test` — Run all tests (unit + e2e) | ||
| - `pnpm test:unit` — Vitest unit tests | ||
| - `pnpm test:e2e` — Playwright e2e tests | ||
| - `pnpm format:check` / `pnpm format:write` — Prettier | ||
|
|
||
| ## Tech stack | ||
|
|
||
| - **Runtime:** Node, pnpm | ||
| - **App:** Next.js, React, Mantine, Tailwind CSS, TanStack Query | ||
| - **Lib:** Rollup, React Compiler | ||
| - **Types:** Zod, Rollup | ||
| - **Testing:** Vitest, Playwright | ||
| - **Linting:** ESLint (flat config), Prettier |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.