-
Notifications
You must be signed in to change notification settings - Fork 13
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
Add separate checkout info block to buildscripts. #3514
Conversation
Of the form: ``` Project: URL Time: time ```
fb8182c
to
b19f652
Compare
2b5df01
to
e8add31
Compare
…nfo. Centralize this so the buildscript and projectfile can remain in sync.
e8add31
to
9f5ffc9
Compare
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.
Looking good! Nice work. Just need some slight iteration on smaller parts. The config change is probably the biggest, but ultimately should lead to an overall cleaner changeset (if not then I'm way off on that review comment; by all means call me on that).
pj, err := model.FetchProjectByName(namespace.Owner, namespace.Project, auth) | ||
if err != nil { | ||
return nil, locale.WrapExternalError(err, "err_fetch_project", "", namespace.String()) | ||
} | ||
|
||
branch, err := model.DefaultBranchForProject(pj) | ||
if err != nil { | ||
return nil, errs.Wrap(err, "Could not grab branch for project") | ||
} |
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 should provide this explicitly. Because we may not be on the default branch, and at this level we have on idea what the intend was. Consuming code won't know that this is setting up any branch related stuff.
Note we could just add an argument for the branch which can be nil, and then we default to this logic if it is nil. My concern is primarily about making the contract with the branch explicit with consuming code.
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 can actually just pass "", and the build script checkout info will silently ignore it (like activestate.yaml with just a commitID and no branch). We cannot explicitly provide a branch argument because state export buildplan
, state artifacts
and state artifacts download
only know about commit ID. We'd have to do branch lookup or ask the user to supply it on the command line. Either one is messy.
Let me know if you disagree.
pkg/checkoutinfo/checkoutinfo.go
Outdated
return nil | ||
} | ||
|
||
// Note: cannot use functions from buildscript_runbit due to import cycle. |
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.
// Note: cannot use functions from buildscript_runbit due to import cycle. |
This is moot; we cannot (should not) use functions from runbits period.
pkg/checkoutinfo/checkoutinfo.go
Outdated
if !c.config.GetBool(constants.OptinBuildscriptsConfig) { | ||
return nil | ||
} |
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.
Please make this a boolean argument passed to new (optinBuidscripts bool
), instead of evaluating it here and having a dependency on config.
pkg/buildscript/buildscript.go
Outdated
return b.raw.CheckoutInfo.Project | ||
} | ||
|
||
func (b *BuildScript) SetProject(url string) { | ||
b.raw.CheckoutInfo.Project = url | ||
} | ||
|
||
func (b *BuildScript) AtTime() time.Time { | ||
return b.raw.CheckoutInfo.AtTime | ||
} | ||
|
||
func (b *BuildScript) SetAtTime(t time.Time) { | ||
b.raw.AtTime = &t | ||
b.raw.CheckoutInfo.AtTime = t |
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 just realized; this probably shouldn't be on raw
at all. raw
covers the build expression portion, which this is not a part of.
That said I don't recall what entanglements exist. I'd suggest changing this to the buildscript (non-raw) package itself if it is trivial, otherwise we can get to it later.
pkg/buildscript/merge.go
Outdated
@@ -57,8 +57,8 @@ func (b *BuildScript) Merge(other *BuildScript, strategies *mono_models.MergeStr | |||
|
|||
// When merging build scripts we want to use the most recent timestamp | |||
atTime := other.AtTime() | |||
if atTime != nil && atTime.After(*b.AtTime()) { | |||
b.SetAtTime(*atTime) | |||
if atTime.After(b.AtTime()) { |
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 think we still need the nil check. Yes any new commits and realistically 99.9% of commits have the atTime var. But commits are final; we do not edit them. Meaning old commits without this are out there, and will forever be out there.
If this is a pain to support we could maybe look into erroring out, but in that scenario we need to outline to the user how they can get out of this broken state. I don't know what that would look like exactly, so if we want to remove support for older commits we'll need to at least file a story to address those older commits with an error.
pkg/buildscript/unmarshal.go
Outdated
return nil, locale.NewExternalError( | ||
"err_buildscript_checkoutinfo", | ||
"Could not parse checkout information in the buildscript. The parser produced the following error: {{.V0}}", err.Error()) |
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.
return nil, locale.NewExternalError( | |
"err_buildscript_checkoutinfo", | |
"Could not parse checkout information in the buildscript. The parser produced the following error: {{.V0}}", err.Error()) | |
return nil, locale.NewInputError( | |
"err_buildscript_checkoutinfo", | |
"Could not parse checkout information in the buildscript. The parser produced the following error: {{.V0}}", err.Error()) |
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.
Also it seems like this error should be more helpful. This isn't just any parsing error; we know it relates specifically to the checkoutinfo section.
// Owner returns the project owner from activestate.yaml. | ||
// Note: cannot read this from buildscript because it may not exist yet. | ||
func (c *CheckoutInfo) Owner() string { | ||
return c.project.Owner() |
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.
Please update all the project methods as legacy, same as we did with the commitID. That extends to the Set..()
ones also.
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.
You said in the previous PR that not everything should go into the checkoutinfo package. If we want to work with projects, we use the project package. If we want to work with buildscripts, we use the buildscript package. By making everything legacy, we're going to be forcing ourselves into buildscripts so that we end up with prime.buildscript.Owner()
, etc. instead of prime.project.Owner()
, etc.
That said, I have serious reservations about this. Not only is it going to balloon the PR by 4x, but I can see us walking back on this and undoing it is going to be really messy. We already walked back the CommitID() -> LegacyCommitID() transition. (That is, we went from project.CommitID()
to localcommit.Get()
and back to project.LegacyCommitID()
via localcommit.Get()
.) It's a mess.
As I've been working on this PR, I've been thinking that if build script parse fails, we have no clue which project we're working on. state reset LOCAL
cannot fix it because we need to parse it to get the project info. Since build scripts are far more brittle than activestate.yaml, this will probably happen pretty frequently as users make edits, or as build scripts change format over time.
As an example, start with a v46 build script and try to do something with this PR. It'll fail with a parse error. There's a lot we'll have to do to make it more robust, especially if we end up priming the primer with a buildscript instead of a projectfile.
Finally, my editor doesn't have method refactoring, so I'd either have to do this by hand or figure out how to use a new editor that has such functionality. If you really want this, can we make it a new ticket? :)
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.
Let's chat on Slack when you're around to figure out the approach. I totally feel you on this starting to feel messy. It's worth having another look at our use-case and seeing if this is in fact the right solution, before we commit to it.
The refactor itself isn't much of an issue here though, with tooling that's really easy to do. I'm more worrying about if this is actually going to save us pain during the transition from as.yaml > buildscripts, rather than cause pain.
host := constants.DefaultAPIHost | ||
if hostOverride := os.Getenv(constants.APIHostEnvVarName); hostOverride != "" { | ||
host = hostOverride | ||
} | ||
pjf := projectfile.NewProjectField() | ||
err := pjf.LoadProject(fmt.Sprintf("https://%s/%s/%s", host, owner, project)) |
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.
Nit: might be nice to add the host stuff directly to the NewProjectField()
constructor. Then just use the setters, and you don't need LoadProject
here at all.
…nfigurable. That way the package doesn't depend on config.
Raw contains the unprocessed checkout info string.
Per conversation on Zoom, closing this for a less invasive solution. |
localcommit
package tocheckoutinfo
checkoutinfo
is a primer property and all runners go through it to get commit IDs and set commit info like owner, name, and branch.buildplanner.GetBuildScript()
to additionally accept an owner, project, branch, and commitID. It uses these fields to construct the "Project" field in the commit info section of buildscripts.state reset LOCAL
will always re-initialize a build script.state install
, etc.).