Using partitions introduces a breaking change
Metadata
Current evaluation
Partition path/working-directory breakage was fixed by the top-level redesign in craft-parts#620, merged via PR #684 (188d9166).
Resolution: closed resolved
Reason: The redesign in canonical/craft-parts#620 moved partitions to the top-level layout and was merged into main by PR #684 at commit 188d9166, resolving the stage and prime path inconsistency.
Evaluated by: mr-cal-bot
No scores available.
Issue body
### Bug Description
When partitions are used, the paths for any particular step in the life cycle of a build are different than in cases where no partitions are present:
```
stage/
├── component
│ ├── foo
│ └── bar
└── default
└── baz
```
(Similarly for `parts/<part>/install` and `prime/`)
Suppose the below `override-stage`:
```
override-stage: |
touch myFile
local/bin/someBinary myFile
```
Just in case no partitions exist, this will work as expected (`myFile` is created and `someBinary` does some act using that file).
In the case where partitions exist, two things change:
1) `myFile` will be located in a different directory than one may think -- `stage/myFile` instead of `stage/default/myFile`
2) `local/bin/someBinary myFile` will fail entirely -- `someBinary` is *not* located in `local/bin`, but instead `default/local/bin`
The resolution to this issue is to specify a fully-qualified path,
```
touch "${CRAFT_STAGE}/myFile"
"${CRAFT_STAGE}/local/bin/someBinary "${CRAFT_STAGE}/myFile
```
Using a fully-qualified path isn't often documented or mentioned (at least in any snap-related documentation I've reviewed). Indeed, existing documentation indicates that the working directory for an override is is precisely `${CRAFT_STAGE|PRIME}`, and leverages non-fully qualified paths, see [here](https://snapcraft.io/docs/overrides).
Changing where `${CRAFT_STAGE|PRIME}` are will break any existing (snap) builds which do not explicitly refer to `.` with `${CRAFT_STAGE|PRIME}`, which is a breaking change from current behavior.
The failure happens in any broad situation where you would expect ENOENT, like:
```
ln -sf ../foo bar/baz
```
As `bar/baz` is actually in `default/bar/baz`.
### To Reproduce
Install snapcraft from a feature branch and create a boilerplate snap:
```
snap switch --channel=latest/edge/components snapcraft; snap refresh snapcraft
# Tested with revision 10677
mkdir test; cd test; snapcraft init
```
Compare outputs from `snapcraft --verbose` using the below `snapcraft.yaml` file, eliminating the `components: ...` stanza to see the current behavior.
### part yaml
```shell
name: my-snap-name # you probably want to 'snapcraft register <name>'
base: core22 # the base snap is the execution environment for this snap
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
This is my-snap's description. You have a paragraph or two to tell the
most important story about your snap. Keep it under 100 words though,
we live in tweetspace and your description wants to look good in the snap
store.
grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots
parts:
my-part:
# See 'snapcraft plugins'
plugin: nil
override-pull: |
set +x
echo my working directory: $PWD
echo what you think my working directory is: ${CRAFT_PART_SRC}
override-build: |
set +x
echo my working directory: $PWD
echo what you think my working directory is: ${CRAFT_PART_BUILD}
override-stage: |
set +x
echo my working directory: $PWD
echo what you think my working directory is: ${CRAFT_STAGE}
override-prime: |
set +x
echo my working directory: $PWD
echo what you think my working directory is: ${CRAFT_PRIME}
components:
test-comp:
type: test
summary: test
description: test
```
### Relevant log output
```shell
dilyn@Ares:~/test -> snapcraft --verbose
Starting snapcraft
Logging execution to '/home/dilyn/.local/state/snapcraft/log/snapcraft-20240227-160254.265019.log'
Starting snapcraft
Logging execution to '/home/dilyn/.local/state/snapcraft/log/snapcraft-20240227-160254.265019.log'
deleting current features configuration
Running on amd64 for amd64
Launching instance...
Creating new instance from remote
Creating new base instance from remote
Creating new instance from base instance
Starting instance
Starting snapcraft
Logging execution to '/root/.local/state/snapcraft/log/snapcraft-20240227-160359.663803.log'
Starting snapcraft
Logging execution to '/root/.local/state/snapcraft/log/snapcraft-20240227-160359.663803.log'
deleting current features configuration
Running on amd64 for amd64
Initializing parts lifecycle
Installing build-packages
Installing build-snaps
Pulling my-part
:: + set +x
:: my working directory: /root/parts/my-part/src
:: what you think my working directory is: /root/parts/my-part/src
Building my-part
:: + set +x
:: my working directory: /root/parts/my-part/build
:: what you think my working directory is: /root/parts/my-part/build
Staging my-part
:: + set +x
:: my working directory: /root/stage
:: what you think my working directory is: /root/stage/default
Priming my-part
:: + set +x
:: my working directory: /root/prime
:: what you think my working directory is: /root/prime/default
Extracting and updating metadata...
Copying snap assets...
Generating snap metadata...
Generated snap metadata
Generating component metadata...
Generated component metadata
Generating snap manifest...
Generated snap manifest
Reading snap metadata...
Running linters...
Running linter: classic
Running linter: library
Creating snap package...
Created snap package my-snap-name_0.1_amd64.snap
Creating component packages...
Packed component 'test-comp' to 'my-snap-name+test-comp_.comp'.
Created component packages
```
Evaluation history
| Date | Model | Scores | Action | Summary |
|---|---|---|---|---|
| stealth/space-bunny-alpha | — | closed resolved | Partition path/working-directory breakage was fixed by the top-level redesign in craft-parts#620, merged via PR #684 (188d9166). | |
| stealth/space-bunny-alpha | — | closed resolved | Partitions changed stage/prime working dirs and ${CRAFT_STAGE}/${CRAFT_PRIME} paths. Closed as fixed by the top-level partition redesign (issue #620), merged via PR #684 (188d9166) from feature/namespaced-partitions. | |
| stealth/space-bunny-alpha | — | closed resolved | Partition support’s path/working-directory break was fixed by the top-level partition redesign in craft-parts#620, merged to main via PR #684 (commit 188d9166). | |
| qwen/qwen3.6-35b-a3b | — | — | Fixed via a redesign in craft-parts issue #620. Partition support previously altered working directory paths, breaking relative path references in build overrides. The redesign resolves the path inconsistency, restoring expected behavior. | |
| qwen/qwen3.6-35b-a3b | — | — | Fixed via a redesign in craft-parts issue #620. Partition usage previously altered working directory paths in lifecycle overrides, breaking relative path references. The redesign resolves the path inconsistency and eliminates the breaking change. | |
| qwen/qwen3.6-35b-a3b | — | — | Fixed via a redesign in craft-parts issue #620. Partition usage previously altered working directory paths, breaking relative paths in snapcraft overrides. The redesign resolves the path mismatch, restoring expected override behavior. | |
| qwen3.6-35b-a3b-mtp-q6 | — | — | Fixed via craft-parts redesign #620. Partition support originally altered override working directories, breaking relative paths. The redesign resolves the path inconsistency, restoring expected behavior without requiring fully qualified paths. |
Update history
No update history recorded yet.
Related work
-
Superseded By:
canonical/craft-parts#620
(confidence 100%)
The closing maintainer identified this issue as fixed by the redesign tracked here.
-
Likely Fixed By:
canonical/craft-parts#684
(confidence 99%)
Merged the completed top-level partition redesign at commit 188d9166.
Related issues
| Issue | Project | State | Summary | Similarity |
|---|---|---|---|---|
| #652 feat(partitions): clean partition directories | craft-parts | merged | Merged #652 via commit 797109e8, adding partition-directory cleanup when partitions are enabled and fixing #634 (CRAFT-2417). | |
| #600 feat(partitions): handle namespaced partitions in utils | craft-parts | merged | Merged into main in commit f387afa5 (PR #600), adding namespaced-partition handling to four partition utilities and resolving craft-parts#596. | |
| #493 partitions: validate usage of partitions in parts | craft-parts | merged | Merged into craft-parts in commit ed20df71 (#493), adding validation of partition usage in filepaths for parts' organize, overlay, stage and prime keywords (CRAFT-1844). | |
| #4463 Enable craft-parts partitions feature | snapcraft | closed | Partitions support landed in merged PR #4493 (commit 070c7e995), enabling partition-backed component lifecycle data and completing #4463. | |
| #754 Document Partitions | craft-parts | closed | Partitions documentation was added and the issue completed by merged PR canonical/craft-parts#763 in commit cdcc9dbc. | |
| #801 fix: partitions break when using special characters | craft-parts | merged | Merged PR #801 fixed CRAFT-3031 lifecycle failures for partition names containing numbers and hyphens; merged as commit ceaf4cda. | |
| #634 Clean partitions directories | craft-parts | closed | Partition directories are now removed during part cleaning when partitions are enabled. Fixed by merged PR canonical/craft-parts#652 in commit 797109e8. | |
| #683 Feature/namespaced partitions | craft-parts | closed | Namespaced-partition support was merged via PR #684 (commit 188d9166) and released in craft-parts 1.28.0. | |
| #497 partitions: add utility to make partition compatible filepaths | craft-parts | merged | Merged #497, adding a utility that converts filepaths into partition-compatible paths for CRAFT-1845; landed as commit 20e994f8. | |
| #627 chore: move partitions to top-level directory | craft-parts | merged | PR #627 merged the top-level partition layout as 9fe38d11, fixing #620 (CRAFT-2389); the completed branch later reached main through #684. |