Skip to content
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

Allow SAVE ARTIFACT after a --push #735

Merged
merged 12 commits into from
Jan 28, 2021
Merged

Allow SAVE ARTIFACT after a --push #735

merged 12 commits into from
Jan 28, 2021

Conversation

dchw
Copy link
Collaborator

@dchw dchw commented Jan 27, 2021

No description provided.

s *solver
opt Opt
resolver *buildcontext.Resolver
builtMain bool
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concept as phases; just need to know one thing instead of a list index... we may need phases in future

@@ -124,6 +125,9 @@ func (b *Builder) convertAndBuild(ctx context.Context, target domain.Target, opt
destPathWhitelist := make(map[string]bool)
manifestLists := make(map[string][]manifest) // parent image -> child images
var mts *states.MultiTarget
depIndex := 0
imageIndex := 0
dirIndex := 0
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indexes need to increase monotonically across all artifacts to avoid overwriting issues, so keep them out side and close on them

}
return sts.SaveLocals
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar things to phases to enable use of the gwClient. However, its not quite the same as before where the state tracks it. Kept it simpler using the existing RunPush struct, and phases only happen here in builder where they are cared about now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to pushing this down and cleaning up some more; perhaps as a separate PR though? Its just touching a lot to do that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you have in mind by "cleaning up some more"?

This looks pretty good BTW.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaning up meaning pushing this down into the states package. Think of it as phases-lite; so the builder doesn't have to be so grabby with SingleTargets fields

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the way it is in this PR is simple enough. We could do that if things get more complex.

llb.WithCustomNamef(
"%sSAVE ARTIFACT %s%s %s AS LOCAL %s",
c.vertexPrefix(false), strIf(ifExists, "--if-exists "), saveFrom, artifact.String(), saveAsLocalTo))
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

State to copy from depends on if we are pushing

@@ -462,7 +458,7 @@ func (l *listener) ExitSaveArtifact(c *parser.SaveArtifactContext) {
saveFrom := l.expandArgs(fs.Args()[0], false)
saveTo = l.expandArgs(saveTo, false)
saveAsLocalTo = l.expandArgs(saveAsLocalTo, false)
err = l.converter.SaveArtifact(l.ctx, saveFrom, saveTo, saveAsLocalTo, *keepTs, *keepOwn, *ifExists)
err = l.converter.SaveArtifact(l.ctx, saveFrom, saveTo, saveAsLocalTo, *keepTs, *keepOwn, *ifExists, l.pushOnlyAllowed)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pushOnlyAllowed is here to signify we have encountered a push. Could rename this var; but didn't because im not globally allowing everything like before.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you wanted you could do

Suggested change
err = l.converter.SaveArtifact(l.ctx, saveFrom, saveTo, saveAsLocalTo, *keepTs, *keepOwn, *ifExists, l.pushOnlyAllowed)
isPushPhase := l.pushOnlyAllowed
err = l.converter.SaveArtifact(l.ctx, saveFrom, saveTo, saveAsLocalTo, *keepTs, *keepOwn, *ifExists, isPushPhase)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ehhhhhhhh that feels like extra ceremony. Not worth it IMO; I would rather rename it to pushEncountered across all of converter if I went renaming; since that preserves the business logic meaning well enough

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷

I like ceremonies :-)

RUN --privileged \
--entrypoint \
--mount=type=tmpfs,target=/tmp/earthly \
-- +copy-test 2>&1 | perl -pe 'BEGIN {$status=1} END {exit $status} $status=0 if /not found/;'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't copy artifacts that were saved in a different targets --push

Copy link
Member

@vladaionescu vladaionescu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good - left an important comment, though.

I assume the output has two ===== SUCCESS ====== lines, right? We should print out a more obvious distinction for the two phases. Maybe ===== Build phase SUCCESS ====== and ===== Push phase SUCCESS ======. Or something like that - whatever looks pretty enough.

func (b *Builder) stateToRef(ctx context.Context, gwClient gwclient.Client, state llb.State, platform *specs.Platform) (gwclient.Reference, error) {
if b.opt.NoCache {
if b.opt.NoCache || b.builtMain {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. I think it should be

Suggested change
if b.opt.NoCache || b.builtMain {
if b.opt.NoCache && !b.builtMain {

Meaning that for the push phase, we do not add the ignore cache flag here (instead we rely on the converter having added this flag to individual commands).

If we add the ignore cache flag here for the push phase, then everything the push phase depends on (including the main phase) will be executed with no cache - so the main phase ends up being executed twice.

Copy link
Collaborator Author

@dchw dchw Jan 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you initially suggested is what I had before; but I noticed that solving the states for the separate artifacts was showing up as cached. I used to have some ls sentinels in here to show when things were being re-run, but I must have pulled them out before swapping to this.

I was trying to get SAVE ARTIFACT inside --push to also not cache when running with --no-cache. Ill rework this some to get both scenarios working

}
return sts.SaveLocals
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you have in mind by "cleaning up some more"?

This looks pretty good BTW.

@dchw
Copy link
Collaborator Author

dchw commented Jan 27, 2021

@vladaionescu I agree on more distinctive success lines. Though, that is also the current behavior.

Sticking the name in the line feels fine; All the alternatives I can think of would require a little more work.

@vladaionescu
Copy link
Member

Yeah, let's stick the name in. I think the current behavior is inconsistent: only prints success once, but can print both success and then fail.

@dchw
Copy link
Collaborator Author

dchw commented Jan 27, 2021

@vladaionescu Updated to your logic.

The one downside to this is that unchanged artifacts after --push still use cache even when specifying --no-cache on the CLI.

@dchw
Copy link
Collaborator Author

dchw commented Jan 27, 2021

How do you feel about solving artifacts state with something like this:

func (b *Builder) artifactStateToRef(ctx context.Context, gwClient gwclient.Client, state llb.State, platform *specs.Platform) (gwclient.Reference, error) {
	if b.opt.NoCache || b.builtMain{
		state = state.SetMarshalDefaults(llb.IgnoreCache)
	}
	return llbutil.StateToRef(ctx, gwClient, state, platform, b.opt.CacheImports)
}

The idea being that we never use cache for artifacts after a push, regardless of the CLI flag.

@vladaionescu
Copy link
Member

Sounds good - I think we had that bug before too.

@dchw
Copy link
Collaborator Author

dchw commented Jan 27, 2021

This is part of the actual solution we plan to ship in place of #728. Relates to #586.

@dchw dchw merged commit 6744f25 into main Jan 28, 2021
@dchw dchw deleted the corey/after-push-5 branch January 28, 2021 18:14
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.

None yet

2 participants