canonical / craft-parts

https://canonical-craft-parts.readthedocs-hosted.com
GNU Lesser General Public License v3.0
11 stars 37 forks source link

Using partitions introduces a breaking change #672

Closed dilyn-corner closed 2 months ago

dilyn-corner commented 8 months ago

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.

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

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

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
syncronize-issues-to-jira[bot] commented 5 months ago

Thank you for reporting us your feedback!

The internal ticket has been created: https://warthogs.atlassian.net/browse/CRAFT-2931.

This message was autogenerated

mr-cal commented 2 months ago

This has been fixed via a redesign: https://github.com/canonical/craft-parts/issues/620