--- name: polylith-migrate-prepare-project description: "[Internal sub-skill of `polylith-migrate-orchestrator`. Do not load directly — load `polylith-migrate-orchestrator` first, which drives all phases.] Clean up the project subfolder and consolidate dependencies after extracting application code into bases." --- # Skill: polylith-migrate-prepare-project ## Goal Clean up the project subfolder (`projects//`) and consolidate dependencies. After this step, the project subfolder should contain only: - Project `pyproject.toml` (with brick references). - Task runners (`Makefile`, `Justfile`). - Project-specific config (e.g., `alembic.ini` **and** its `alembic/` directory). - Compatibility shim (only when `SHIM_STRATEGY=shim`). ## Inputs From `migration//state.md`: - `PROJECT_DIR` - `TARGET_TOP_NS` - `ALIAS` (optional: `GROUP`) - Verification commands. From `migration//manifest.md`: - Infra files list. > All inputs from `state.md` are assumed to satisfy the validation rules in `polylith-migrate-discover` (`### Validation rules`). Validate before proceeding. ## Steps ### 1. Verify Project Subfolder - Run `directory_tree` on `projects/${PROJECT}/` to confirm only infra and config files remain. ### 2. Update `pyproject.toml` - Add brick references to `[tool.polylith.bricks]`: ```toml [tool.polylith.bricks] "../../bases/${TARGET_TOP_NS}/${INITIAL_BASE_NAME}" = "${TARGET_TOP_NS}/${INITIAL_BASE_NAME}" ``` - Register the project alias and group in `workspace.toml` (if provided): ```toml [tool.polylith.projects.alias] ${PROJECT} = "${ALIAS}" [tool.polylith.projects.groups] ${GROUP} = ["${PROJECT}"] ``` ### 3. Move Tests to Workspace Level - Move `tests/` to `test//`, where `` is a **valid Python package name**. ⚠ `${PROJECT}` frequently contains hyphens (e.g. `order-management-api`), which are **illegal in a package name** and break pytest's package-style import. Derive an underscore name — the workspace's `_service` convention is a good default (e.g. `order_management_service`). Record `` in `state.md`. - If the moved tests import the old package by name (e.g. `from tests.fixtures import …` / `from tests.helpers import …`), rewrite those to the new name (`from .fixtures import …`). Brick imports (`.*`) are absolute and need no change. - Update `RUN_TEST_CMD` in `migration/${PROJECT}/state.md` to point to the new location. - Update mock patch strings in test files if paths changed. > Per-brick test redistribution (`test////`) is handled later in `polylith-migrate-refactor-tests` — this step only lifts tests to the workspace level. See that skill for the shared-helper / namespace-merge caveats before splitting further. ### 4. Move Infrastructure Folders - Move **deployment** infra folders (e.g., `helm/`, `k8s/`, `kustomize/`, `skaffold/`) to `infra//${PROJECT}/`. - 🔒 **Secret & `.gitignore` check before the move.** Infra folders frequently carry secret material (e.g. `values-secret.yaml`, `*.env`, sealed-secret sources, TLS keys). Two hazards when relocating them: - **`.gitignore` scope shifts.** Ignore rules scoped to the **old** path stop matching at the new `infra//${PROJECT}/` path, so a previously-ignored secret file can become **tracked** after the move. Verify the destination is still covered by `.gitignore` for anything that was ignored at the source. - **Inline secrets.** Scan the moved manifests/values for inline credentials before committing. Do **not** commit newly-tracked secrets; have the user move them to an ignored path or a secret manager first. - **Keep `alembic/` together with `alembic.ini` in the project** — do **not** split them. `alembic.ini`'s `script_location` points at `alembic/` relatively, and `alembic/env.py` imports the project's bricks; separating them breaks migrations. (Alembic is project-specific config, which the project subfolder is allowed to keep.) ⚠ `alembic.ini` commonly holds a `sqlalchemy.url` with DB credentials — if it is not already tracked, do not newly commit it with a literal credential; reference an env var instead. - ⚠ **Deploy-path breakage:** moving infra breaks deploy scripts / `skaffold` / CI that hardcode the old paths. If you **cannot verify the deploy** in the migration environment (no deploy / manifest-diff cycle available), it is acceptable to **defer the infra move and document it** in `state.md` rather than relocate blindly. Otherwise, update the referencing scripts and record the change. Prefer updating references over committing a **symlink**: a committed symlink can point outside the repo and behaves inconsistently across checkouts/OSes — if you must use one as a transition, keep it within the repo, record it in `state.md`, and schedule its removal. ### 5. Consolidate Dependencies - Move third-party dependencies with version constraints to the workspace root `pyproject.toml`. - Move dev/test/tooling dependencies to the workspace root. - List runtime dependencies **without version numbers** in the project `pyproject.toml`. - Sync the virtual environment with the project's package manager (e.g. `uv sync`, `pdm install`, `poetry install` — match `PACKAGE_MANAGER` in `state.md`). - Verify dependencies, substituting your package manager's run prefix (`` = `uv run` / `pdm run` / `poetry run` / bare in an activated venv): ```bash pip list # Confirm all dependencies are installed python -c "import " # Verify key dependencies are available ``` ## Verify - `RUN_TEST_CMD` succeeds against the **new** test location. - If set, `RUN_LINT_CMD` and `RUN_TYPECHECK_CMD` succeed. - Run `POLY_CMD_PREFIX check` to validate the workspace structure. - Run `POLY_CMD_PREFIX info` to inspect the workspace and confirm the project is correctly registered. ## Common failure modes | Symptom | Likely cause | Remediation | |---------|--------------|-------------| | `RUN_TEST_CMD` collects 0 tests after step 3 | The command in `state.md` still references the old `projects/${PROJECT}/tests` path. | Update `RUN_TEST_CMD` to the new `test/${PROJECT}/` location. Also check `[tool.pytest.ini_options].testpaths` / `rootdir` / `conftest.py` discovery. | | Tests fail with `ModuleNotFoundError` on internal imports | Tests use `from tests.fixtures import …` and the `tests` package name changed. | Update test imports to the new test root path. If many tests reference the old name, consider keeping `tests` as the leaf directory and only renaming the parent. | | `mock.patch("")` fails with `AttributeError` | Mock patch strings reference moved modules. | Update patch strings to the new module paths. Use `grep -r 'patch("' test/` to find them all. | | Infra folder move breaks deploy scripts that hardcoded paths (e.g., `helm//values.yaml`) | Deploy scripts haven't been updated to the new `infra/): phase — prepare-project" ``` Substitute ``, ``, and `` from `state.md` and the orchestrator's phase table. Do not proceed to the next phase without a clean commit — the per-phase commit is the rollback point for the next phase's failure-mode tables.