Skip to content

Add interactive project upgrade wizard#1063

Draft
Soner (shyim) wants to merge 56 commits into
nextfrom
claude/great-carson-fvQki
Draft

Add interactive project upgrade wizard#1063
Soner (shyim) wants to merge 56 commits into
nextfrom
claude/great-carson-fvQki

Conversation

@shyim

Copy link
Copy Markdown
Member

Summary

Implements an interactive upgrade wizard for Shopware projects that guides users through the upgrade process with a TUI interface. This mirrors the behavior of the shopware/web-installer but runs from the command line.

Key Changes

New Packages

  • internal/projectupgrade/ - Core upgrade logic package containing:

    • wizard.go - Interactive TUI-based upgrade wizard using Bubble Tea
    • composer.go - Composer.json rewriting for target versions
    • plugins.go - Plugin compatibility resolution and constraint bumping
    • registry.go - Package registry abstraction for version lookups
    • releases.go - Version filtering and selection logic
    • Comprehensive test coverage for all modules
  • cmd/project/project_upgrade.go - New project upgrade command with:

    • Interactive wizard mode (default when TTY available)
    • Headless mode for CI/CD pipelines
    • Git working tree validation
    • Composer-managed plugin verification

Upgrade Workflow

The wizard guides users through:

  1. Welcome screen - Confirm upgrade intent
  2. Version selection - Choose target Shopware version
  3. Compatibility check - Query Shopware Account API for extension compatibility
  4. Review - Confirm selected version and changes
  5. Execution - Run upgrade tasks with live progress:
    • Back up composer.json
    • Clean up stale recipe files
    • Resolve incompatible custom plugins
    • Rewrite composer.json
    • Run composer update --with-all-dependencies
    • Execute bin/console system:update:prepare
    • Execute bin/console system:update:finish

Plugin Resolution

  • Detects incompatible custom plugins by checking Shopware package constraints
  • Attempts to find compatible versions via registry (Packagist or Shopware Store)
  • Bumps constraints to compatible versions when available
  • Removes plugins with no compatible release
  • Restores composer.json on failure

Registry System

  • CombinedRegistry routes lookups to appropriate backend (Store vs Packagist)
  • PackagistRegistry queries repo.packagist.org with minified format support
  • Extensible interface for custom registry implementations

Supporting Changes

  • Enhanced internal/git/ with IsRepository() and WorkingTreeStatus() functions
  • Extended internal/flexmigrator/ with CleanupByHash() for recipe file cleanup
  • Version filtering logic matching web-installer behavior

Implementation Details

  • Uses Bubble Tea for interactive TUI with spinner animations
  • Streams subprocess output (composer, console commands) to live log view
  • Graceful error handling with composer.json restoration on failure
  • Context-based cancellation support for long-running operations
  • Comprehensive test coverage including wizard state machine and plugin resolution

https://claude.ai/code/session_01F4pXpGEuJGsxpfTudpnoLo

MJML 5 ignores <mj-include> by default for security reasons and
sandboxes resolved include paths to the file's own parent directory,
which silently breaks templates that share partials from a sibling
_includes folder.

Expose two new project-config knobs:

  build:
    mjml:
      enabled: true
      search_paths:
        - custom/static-plugins
      allow_includes: true

For the common layout, where partials live somewhere inside an existing
search_path tree, allow_includes: true is enough: each search_path is
automatically added to the mj-include allowlist for files compiled
within it, so <mj-include path="../_includes/header.mjml"> from a
sibling mail-type dir just works.

For partials living outside any search_path, include_paths is an
escape hatch:

  build:
    mjml:
      allow_includes: true
      include_paths:
        - shared/email/_includes

Relative include_paths entries are resolved against the project root,
absolute entries are used as-is. Any value in include_paths implies
allow_includes.

Under the hood, allow_includes forwards --config.allowIncludes=true to
mjml, and the merged allowlist (search_path root + resolved extras) is
JSON-encoded and forwarded as --config.includePath=[...].

Compile() and ProcessDirectory() now take a CompileOptions struct.
mjml.NewCompileOptions() builds per-search-path options with the auto
search_path allowlisting. ConfigBuildMJML.ResolveIncludePaths() mirrors
GetPaths semantics for the user-supplied extras. Schema regenerated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
t.TempDir() cleans up its directory automatically, so the explicit
os.Remove was a no-op that also tripped golangci-lint's errcheck.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps the all group with 2 updates: [golang.org/x/image](https://github.com/golang/image) and [golang.org/x/net](https://github.com/golang/net).


Updates `golang.org/x/image` from 0.40.0 to 0.41.0
- [Commits](golang/image@v0.40.0...v0.41.0)

Updates `golang.org/x/net` from 0.54.0 to 0.55.0
- [Commits](golang/net@v0.54.0...v0.55.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-version: 0.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: golang.org/x/net
  dependency-version: 0.55.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the all group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [docker/github-builder/.github/workflows/build.yml](https://github.com/docker/github-builder) | `1.8.0` | `1.9.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.0.0` | `4.1.0` |
| [docker/login-action](https://github.com/docker/login-action) | `4.1.0` | `4.2.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `6.0.0` | `6.1.0` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `7.1.0` | `7.2.0` |
| [step-security/harden-runner](https://github.com/step-security/harden-runner) | `2.19.3` | `2.19.4` |
| [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) | `9.2.0` | `9.2.1` |
| [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `7.2.1` | `7.2.2` |


Updates `docker/github-builder/.github/workflows/build.yml` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/docker/github-builder/releases)
- [Commits](docker/github-builder@c2782c5...0738332)

Updates `docker/setup-buildx-action` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](docker/setup-buildx-action@4d04d5d...d7f5e7f)

Updates `docker/login-action` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](docker/login-action@4907a6d...650006c)

Updates `docker/metadata-action` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](docker/metadata-action@030e881...80c7e94)

Updates `docker/build-push-action` from 7.1.0 to 7.2.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](docker/build-push-action@bcafcac...f9f3042)

Updates `step-security/harden-runner` from 2.19.3 to 2.19.4
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](step-security/harden-runner@ab7a940...9af89fc)

Updates `golangci/golangci-lint-action` from 9.2.0 to 9.2.1
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](golangci/golangci-lint-action@1e7e51e...82606bf)

Updates `goreleaser/goreleaser-action` from 7.2.1 to 7.2.2
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](goreleaser/goreleaser-action@1a80836...5daf1e9)

---
updated-dependencies:
- dependency-name: docker/github-builder/.github/workflows/build.yml
  dependency-version: 1.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: docker/login-action
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: docker/metadata-action
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: docker/build-push-action
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: step-security/harden-runner
  dependency-version: 2.19.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: golangci/golangci-lint-action
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: goreleaser/goreleaser-action
  dependency-version: 7.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the all group in /internal/verifier/php with 2 updates: [shopwarelabs/phpstan-shopware](https://github.com/shopwareLabs/phpstan-shopware) and [rector/rector](https://github.com/rectorphp/rector).


Updates `shopwarelabs/phpstan-shopware` from 0.2.0 to 0.2.2
- [Release notes](https://github.com/shopwareLabs/phpstan-shopware/releases)
- [Commits](shopware/phpstan-shopware@0.2.0...0.2.2)

Updates `rector/rector` from 2.4.3 to 2.4.4
- [Release notes](https://github.com/rectorphp/rector/releases)
- [Commits](rectorphp/rector@2.4.3...2.4.4)

---
updated-dependencies:
- dependency-name: shopwarelabs/phpstan-shopware
  dependency-version: 0.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: rector/rector
  dependency-version: 2.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the all group in /internal/verifier/js with 3 updates: [stylelint](https://github.com/stylelint/stylelint), [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `stylelint` from 17.11.1 to 17.12.0
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](stylelint/stylelint@17.11.1...17.12.0)

Updates `typescript-eslint` from 8.59.4 to 8.60.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.60.0/packages/typescript-eslint)

Updates `vitest` from 4.1.6 to 4.1.7
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.7/packages/vitest)

---
updated-dependencies:
- dependency-name: stylelint
  dependency-version: 17.12.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: typescript-eslint
  dependency-version: 8.60.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: vitest
  dependency-version: 4.1.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
…erifier/php/all-33b5e38e55

fix(deps): bump the all group in /internal/verifier/php with 2 updates
…06557818c8

fix(deps): bump the all group with 8 updates
…6b5f9d

fix(deps): bump the all group with 2 updates
…al/verifier/js/all-677ee332d8

fix(deps): bump the all group in /internal/verifier/js with 3 updates
Automatically generate checksum.json for all extensions after asset
builds during shopware-cli project ci. This enables integrity
verification for extensions deployed via CI pipelines.

- Skips extensions that already have checksum.json
- Non-fatal: warns on failure but continues with other extensions
- Reuses existing GenerateChecksumJSON with XXH128 algorithm

Closes #1058
…ums-in-ci

feat: generate extension checksums during project CI builds
feat(mjml): allow mj-include via build config
- Generate coverage profile during test run via COVERAGE_FILE env var
- Convert Go coverage to Cobertura XML using gocover-cobertura
- Upload coverage report to GitHub's code coverage API
- Add code-quality: write permission to test workflow
Mirrors the shopware/web-installer Update flow so projects can be
upgraded from the command line:

- Reads the current Shopware version from composer.lock
- Filters available releases the same way as ReleaseInfoProvider (next
  major + remaining patches of the current major, no RCs)
- Prompts for the target version (or `--to` flag), then runs the
  existing extension compatibility check before continuing
- Backs up composer.json, cleans up recipe-managed stale files by MD5,
  removes incompatible symlinked custom plugins, rewrites composer.json
  (shopware/core + administration/storefront/elasticsearch when
  required, minimum-stability for RC targets, symfony/runtime
  constraint relax)
- Runs `composer update --with-all-dependencies --no-scripts` and
  restores the backup on failure
- Runs `bin/console system:update:prepare` and `system:update:finish`
- Tracks the outcome

Extracts the MD5-based cleanup map from `flexmigrator.Cleanup` into a
new `flexmigrator.CleanupByHash` helper so the upgrade flow can reuse
it without also deleting flex-migration-specific files.
The interactive flow is now a small bubbletea Program that mirrors
the install-wizard / setup-guide visual idiom:

- Welcome card (cowsay mascot) with current version + project root
- Step 1: select target version (RenderSelectList)
- Step 2 (when extensions are installed): compatibility lookup with
  spinner, then per-extension checkmark/blocker icons
- Step 3: review card with from/to/executor and the full task list
- Step 4: running phase with per-task spinner / checkmark / failure
  icons and a live tail of the composer/console output
- Done card summarising success or failure, restored composer.json on
  failure, and listing any plugins that were dropped

Non-interactive mode (`-n`) and `--to <version>` continue to use the
existing headless flow so CI runs are unchanged.
The upgrade rewrites composer.json, deletes recipe-managed files, and
drops incompatible plugins. Mixing those rewrites with unrelated
uncommitted changes makes it hard to review the diff or roll back, so
the command now refuses to run with a dirty working tree.

- Adds `git.IsRepository` and `git.WorkingTreeStatus` helpers so other
  commands can reuse the same checks.
- When the project directory is not inside a git working tree the
  check is skipped (greenfield projects, tarball-installed copies).
- The error message lists up to ten changed paths and points at
  `--allow-dirty` as the explicit override.
…gins

Before doing anything destructive, `project upgrade` now requires every
directory under custom/plugins/ to be tracked by composer (i.e. appear
in vendor/composer/installed.json). When plain file-drop plugins are
detected the upgrade aborts with a pointer at
`project autofix composer-plugins`. The `--allow-non-composer` flag
opts out for projects that have not migrated yet.

When a composer-managed plugin's declared shopware/core constraint is
not satisfied by the upgrade target, the resolver now queries a package
registry (repo.packagist.org for plain composer packages,
packages.shopware.com for store.shopware.com/* packages) for the newest
release whose require.shopware/core does satisfy the target and rewrites
the composer.json constraint to "^<that-version>". Only when no
compatible release is found does the plugin fall back to being dropped,
matching the old behaviour.

The Shopware Packages token is read from SHOPWARE_PACKAGES_TOKEN or the
project's auth.json. When neither is present and the project has store
plugins the interactive flow prompts for the token (and skips store
lookups gracefully if the prompt is left empty).

The wizard's "Done" card now lists bumped constraints (old → new) in
addition to the removed plugins, so users can see exactly what shifted.

Tests: 9 new tests covering the resolver (bump, remove, registry error,
no installed.json), FindNonComposerPlugins, and the
ensureAllPluginsAreComposerManaged pre-flight check. All packages pass.
- Drop trailing punctuation from the dirty-git-tree and
  non-composer-plugin error strings (ST1005).
- Make the phase / task-status switches exhaustive (exhaustive).
- Rewrite the compat-result if/else chain as a tagless switch
  (gocritic).
- Rename the `max` parameter in `truncate` to `maxRunes` so it stops
  shadowing the predeclared builtin (predeclared).
- Wrap `resp.Body.Close()` in a small `closeBody` helper so we don't
  ignore its error inline (errcheck).
- Rename the test-only `stringErr` type to `testError` to match the
  `xxxError` naming convention (errname).
- Add `t.Parallel()` to the render-smoke subtest (tparallel).
- Drop the unused `upgradeDoneMsg` type (unused).
- Drop the unused `projectRoot` parameter from `runCompatibilityCheck`
  (unparam).
feat: add code coverage upload via actions/upload-code-coverage
…cate-appends

Make `ConfigDump.EnableClean` idempotent on repeated calls
…ir-cleanup

Remove redundant temp dir cleanup in `internal/shop/config_test.go`
Replace unquoted $COVER_FLAG string variable with a bash array
COVER_FLAGS=() so that when coverage is not requested, the empty
array expands to nothing instead of an empty-string argument to
go test.
Soner (shyim) and others added 6 commits May 27, 2026 05:26
fix: use array for COVER_FLAGS to safely handle empty case
- Move cleanup CI logic from cmd/project/ci.go to internal/extension/cleanup_ci.go
- Add comprehensive tests for cleanup functions
- Clean up checksum test file
The registry duplicated the packagist HTTP client, the composer v2
minified-metadata unminifier, the response-body closer, and the
packages.json fetch. Move the generic lookups into the packagist
package instead:

- Add packagist.GetComposerPackageVersions(ctx, name) for any composer
  package and rebuild GetShopwarePackageVersions on top of it.
- Add a Require field to packagist.PackageVersion so store-package
  metadata carries its shopware/core constraint.

PackagistRegistry and ShopwareStoreRegistry now delegate to the
packagist package, dropping ~120 lines of duplicated logic.
…sums-after-optimization

fix: patch extension checksums to remove entries for files deleted during optimization
Write merged snippet files to a temp directory instead of directly into
the extension root folder. This avoids clobbering existing locale files
(e.g. en-GB) that happen to share the same name as a snippet language.
…ot-locale

fix: prevent snippet merge from overwriting root locale files
@lasomethingsomething

Copy link
Copy Markdown
Contributor

Next step: prep this for team demo

dependabot Bot and others added 3 commits May 29, 2026 02:39
---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-version: 2.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: rector/rector
  dependency-version: 2.4.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
…erifier/php/all-fb41d19606

fix(deps): bump the all group in /internal/verifier/php with 2 updates
The upgrade flow parsed vendor/composer/installed.json by hand, resolved
install paths, and re-implemented composer version-constraint checks.
Move that composer logic into the packagist package where the rest of
the composer model (composer.json, composer.lock, auth.json) already
lives:

- packagist.InstalledJson / InstalledPackage / ReadInstalledJson model
  and read vendor/composer/installed.json.
- InstalledPackage.InstallDirName resolves a package's install location
  (symlinks included) to its directory name under a given base dir.
- packagist.ConstraintsSatisfiedBy reports whether a require map's
  constraints for a set of packages are satisfied by a target version.
- packagist.BumpConstraint turns a concrete version into a caret
  constraint.

projectupgrade now consumes these helpers and keeps only the upgrade
policy (which Shopware packages matter, registry resolution). Its
duplicate ShopwarePackages list is reused in place of the former
pluginShopwarePackages. plugins.go drops ~145 lines.
@shyim Soner (shyim) force-pushed the claude/great-carson-fvQki branch 2 times, most recently from 742a657 to 256390f Compare May 29, 2026 07:15
…teps

Several fixes to the project upgrade flow surfaced by real upgrades:

- Treat store "with new Shopware version" status as resolvable, not a
  blocker. Classification now keys on the semantic status name
  (notCompatible) instead of the display color, matching the platform's
  ExtensionCompatibility constants.
- Resolve plugin constraints for vendor-installed plugins, not just those
  under custom/plugins/. Scope candidates by the root composer.json require
  so store plugins (swag/*, frosh/*) installed into vendor/ get bumped too.
- Look up store-owned, vendor-named plugins via the store registry first
  (falling back to Packagist) instead of routing only by name prefix.
- Run system:update:prepare before composer update so it executes on the
  still-installed Shopware; restore composer.json if prepare fails.
- Center the wizard in the terminal and replay the full failed-step log
  after the alt-screen tears down.

Adds tests for status classification, vendor-installed resolution, registry
routing, and upgrade step ordering.
@shyim Soner (shyim) force-pushed the claude/great-carson-fvQki branch from 39ef87d to 951109a Compare May 29, 2026 07:23
Claude (claude) and others added 6 commits May 29, 2026 08:15
Project creation now validates the project name against the rules for a
Docker Compose project name. Names containing umlauts, spaces, dots or
other characters that Docker Compose would silently strip or reject (it
only allows alphanumerics, dashes and underscores, starting with a letter
or digit) are now rejected up front, both in the interactive form and
when the name is passed as an argument.
Docker Compose requires project names to contain only lowercase letters,
digits, dashes and underscores and to start with a lowercase letter or
digit. The previous regex also accepted uppercase letters (e.g. MyShop),
which would later fail once the generated Docker setup runs from the
project directory. Tighten the regex to lowercase-only and treat uppercase
names as invalid.
The interactive create form now validates the project name as the user
types instead of only on submit. The input description switches to a
red-highlighted hint describing the allowed characters whenever the
current value is not a valid Docker Compose project name, and reverts to
the normal help text once it is valid. The allowed-character rule is
shared between this live hint and the submit-time validation error.
Replace the wizard's hand-rolled version-list cursor and rendering with the
reusable tui.SelectList component: it owns the cursor, windowing, paging
(PgUp/PgDn, Home/End) and the navigation shortcuts, so the wizard only
forwards keys and renders.
Validate project names for Docker Compose compatibility
Claude (claude) and others added 8 commits June 1, 2026 12:17
The upgrade used to drive the lifecycle by hand: stash a composer.json
backup, run system:update:prepare on the old code, swap vendor via
composer update, run system:update:finish on the new code, and rewind
composer.json on any failure. shopware-deployment-helper already owns
that lifecycle (prepare, migrations, finish, theme compile, plugin
refresh) and is what production deployments run, so the wizard now
delegates to it instead of orchestrating each step itself.

- UpdateComposerJson additionally calls EnsureRequire to add
  shopware/deployment-helper to composer.json when the project does
  not require it yet. The subsequent composer update pulls it in.
- The wizard's task list drops the dedicated "Back up composer.json",
  "system:update:prepare" and "system:update:finish" tasks and gains
  a single "vendor/bin/shopware-deployment-helper run" task that runs
  after composer update. Five tasks total instead of seven.
- All composer.json backup / restore plumbing is removed from both
  the wizard and the headless flow. The pre-flight clean-git-tree
  check already guarantees `git checkout composer.json composer.lock`
  is a one-liner if the user wants to revert.
- packagist.ComposerJson.EnsureRequire is the new shared helper for
  "add this require entry if missing"; the devtui setup guide reuses
  it in place of its private branch.
The compatibility phase used to call the Shopware account API to ask
"which extensions are blocked by this Shopware version?". The same
question is already answered by the composer-managed plugin metadata
the resolver consults right after: for each platform plugin, its
require.shopware/* tells us whether it satisfies the target, and the
registry (Packagist + Shopware store) tells us whether a newer
release would. Use that consistent source instead and drop the
account API dependency from the upgrade flow:

- projectupgrade.CheckPluginCompatibility is a dry-run of the
  resolver: for every shopware-platform-plugin in composer.json's
  require it reports CompatCompatible / CompatUpdatable (with the
  target version) / CompatBlocker (no compatible release) /
  CompatUnknown (registry unreachable - e.g. store token missing).
- The wizard's loadCompatibility now calls that instead of
  account_api.GetFutureExtensionUpdates, and renders rows as
  `name — current → new` (Updatable) or `name — current — status`.
- The headless runCompatibilityCheck mirrors the wizard's logic and
  renders a Plugin / Current / Status table.
- packagist.InstalledPackage gains a Version field so the report can
  show the installed version.
- WizardOptions.Extensions and the "skip compat phase when no
  extensions" branch are removed - the phase always runs against the
  composer data, and the step counter is always 4.

The account-api package itself stays in the codebase; it is still
used by `project upgrade-check` and other commands that genuinely
need the store's extension catalog.
fix(project): guard project ci on dirty local worktrees
…vQki

Resolve conflicts in cmd/project (ci.go imports, ci_test.go helpers,
project_create.go decomposition). Revert internal/git additions
(IsRepository/WorkingTreeStatus) in favor of origin/main's
IsWorkingTreeDirty; rewire project upgrade clean-tree check accordingly.
Replace the homegrown registry + constraint resolver with composer itself.
The upgrade now runs `composer require --no-install -W shopware/core:<target>
<plugins…>` and reads composer's verdict: success means the upgrade resolves,
a non-zero exit with "could not be resolved" means it doesn't, and the
blocking plugin(s) are dropped and retried.

- new composer_resolve.go: DryRunRequire (compat preview, --dry-run, nothing
  written) and ApplyRequire (real require, drops unresolvable plugins and
  retries). Store plugins resolve via the project's own composer config /
  auth.json - no token plumbing.
- delete registry.go, compatibility.go and the version-finding half of
  plugins.go; keep FindNonComposerPlugins and the ResolveResult reporting type.
- wizard + command rewired off Registry; compat phase shows composer's own
  resolution and the plugins it cannot resolve.
- drop now-unused packagist.ConstraintsSatisfiedBy / BumpConstraint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants