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
many: extract lifecycle ordering into own module #2159
many: extract lifecycle ordering into own module #2159
Conversation
Currently the snapcraft CLI has step names and ordering hard-coded in a number of places, and those areas where it isn't hard-coded, a difficult-to-read index method is used. Simplify and extract this logic into a single module used by the others to determine lifecycle steps and ordering. Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
SNAPCRAFT_INTERNAL_DIR = os.path.join('snap', '.snapcraft') | ||
STEPS_TO_AUTOMATICALLY_CLEAN_IF_DIRTY = {'stage', 'prime'} | ||
STEPS_TO_AUTOMATICALLY_CLEAN_IF_DIRTY = {steps.STAGE, steps.PRIME} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would this look better if it were an attribute of the step?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, excellent idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
sources, | ||
states, | ||
steps, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this import style really drives me nuts for some reason I cannot explain 😛
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, this one was long enough I had to split it, sorry!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you use autopep8 it will use the format I like :-P
next_step = step | ||
|
||
return next_step | ||
latest_step = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if what we return is the next_step, should what we eval be the current_step instead of the latest_step? I am not sure why, but calling this latest_step confuses me, we had this conversation already as this is triggering things (I think we even opened a bug for this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, everything revolves around latest_step
now it seems
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No logic has changed here, it was just called "last step" which never felt quite right, so I changed it to "latest". Everything naturally revolves around which step was run most recently, since they build on each other. Do you prefer another name?
snapcraft/internal/steps.py
Outdated
|
||
|
||
class Step: | ||
def __init__(self, name: str) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am just going to throw this out, but what if instead of keeping a tight coupling with STEPS
and those index
calls to know where it lives we create the Step instance with knowledge of the next step and the previous step, kind of like a linked list and create a map of step names to the instances?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I thought about that, but ended up having two issues:
- Order needs to be provided somehow, whether that's by providing a list giving the order or by hard-coding it into each
Step
instance. The former seemed simpler to understand and modify than the latter (which also seems potentially error-prone). - We need a way to know which step is first. The
STEPS
variable provides that knowledge (STEPS[0]
).
Basically, I liked the idea of having order solidly maintained in a single, easy-to-understand place rather than spread through multiple classes and needing to know that PULL is the first step. It's an interesting idea, though. Let me try it real quick, I think it's a small change. Then we can see what we think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, just pushed it up. Let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed offline, and I've moved it back to a list, but kept the same methods.
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
Codecov Report
@@ Coverage Diff @@
## master #2159 +/- ##
==========================================
- Coverage 91.34% 91.26% -0.08%
==========================================
Files 194 195 +1
Lines 12246 12317 +71
Branches 1820 1827 +7
==========================================
+ Hits 11186 11241 +55
- Misses 718 730 +12
- Partials 342 346 +4
Continue to review full report at Codecov.
|
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
snapcraft/internal/lxd/_project.py
Outdated
@@ -112,10 +112,10 @@ def clean(self, parts: List[str], step: str): | |||
print('Deleting {}'.format(self._container_name)) | |||
subprocess.check_call([ | |||
'lxc', 'delete', '-f', self._container_name]) | |||
step = 'pull' | |||
step = steps.PULL.name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see two options here, but one thing first, we should rename the signature of this method to taking step_name
instead of step
or have it pass down an actual Step
, where a possible value is None
and move the DEPRECATED warning a level up when using strip
passing it the appropriate step.
If using the former, I wouldn't get the name just to get the step again, but instead, only create the step for the case of strip
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, fixed by passing down a Step.
snapcraft/internal/steps.py
Outdated
return hash(self.name) | ||
|
||
def __repr__(self): | ||
return 'snapcraft.internal.steps.Step({!r})'.format(self.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would of been nice to have some sort of __modpath__
to not hardcode this, closest I know of is __file__
, but it will look too hacky. If we ever move this module, this change will most likely go unnoticed, so why not remove the leading qualifiers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, you're right. I'm mostly going off of python docs here that say:
[...] If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value
So I added the qualifiers. I agree that it's just asking to break though, and I question its usefulness anyway. This is really just to make test failures nice, so we can make it whatever we want. I'll remove the leading qualifiers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
PULL = Step('pull', False) | ||
BUILD = Step('build', False) | ||
STAGE = Step('stage', True) | ||
PRIME = Step('prime', True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add STRIP = PRIME
with a comment about it being there for backwards compat?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't really help us since the step .name
would still be prime
. It's okay though, I think we can handle this a level above rather than pushing deprecation all the way down here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one last round of changes. Looking good.
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
snapcraft/cli/lifecycle.py
Outdated
if build_environment.is_host: | ||
step = step or steps.next_step(step).name | ||
|
||
if step: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it gets confusing a bit when step
can be a step_name
or an actual instance of Step
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, fixed by using an identifier decl for click to make it use a different parameter name.
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
\o/ |
./runtests.sh static
?./runtests.sh unit
?Currently the snapcraft CLI has step names and ordering hard-coded in a number of places, and those areas where it isn't hard-coded, a difficult-to-read index method is used. Simplify and extract this logic into a single module used by the others to determine lifecycle steps and ordering.