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

[JENKINS-38153] Adding synthetic stage marker. #13

Closed
wants to merge 10 commits into from

Conversation

abayer
Copy link
Member

@abayer abayer commented Sep 13, 2016

JENKINS-38153

Also adding synthetic stages for pre-build stuff.

cc @reviewbybees esp @vivek

Also adding synthetic stages for pre-build stuff.
@ghost
Copy link

ghost commented Sep 13, 2016

This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation.

@abayer
Copy link
Member Author

abayer commented Sep 13, 2016

Also cc @svanoort

@svanoort
Copy link
Member

svanoort commented Sep 13, 2016

Agree with adding a new action -- however I think this is where we should do a trivial JENKINS-26522 implementation. Give me a minute I'm going to hack together something for you :)

"Synthetic" would be one of the annotations for us, just one of many, used here.

Need a bit of time in order to be able to give you a full review.

@svanoort
Copy link
Member

@abayer and @vivek I like the basic ideal but think a JENKINS-26522 implemetation around arbitrary annotations like this is better and more flexible:

jenkinsci/workflow-api-plugin#12 <-- POC concept

In that case, we'd use a tag "SYNTHETIC" on the action.

@abayer
Copy link
Member Author

abayer commented Sep 13, 2016

@svanoort Well, that's part of it, but we did need more metadata than just the tag - we're also recording the execution context (currently the only options are pre-build/post-build, but I have a feeling we'll add more to that in the future).

@svanoort
Copy link
Member

svanoort commented Sep 13, 2016

execution context

Yeah you're just annotating which synthetic stage type it is. That's a SYNTHETIC tag and/or SYNTHETIC_PRE/SYNTHETIC_POST.

Are there additional requirements/plans that have not been disclosed yet that you'd like to disclose now?

@abayer
Copy link
Member Author

abayer commented Sep 13, 2016

Awwww, I have to translate everything to string tags? I'm back in AWS-land! =)

@svanoort
Copy link
Member

@abayer Okay, but implementation-nitpicking aside: don't tell me you don't want JENKINS-26522... ;) Or that you will get to be the trailblazer use case to justify it, with pipeline model definitions.

@abayer
Copy link
Member Author

abayer commented Sep 13, 2016

Yes, I do want that. =)

Conflicts:
	src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy
@jglick
Copy link
Member

jglick commented Sep 14, 2016

Seems hackish. Better to define a simple Step with a block and whatever Actions you need, possibly though not necessarily including LabelAction.

@svanoort
Copy link
Member

@abayer If we pull in the TagsAction here I think will be ready for merge?

@abayer
Copy link
Member Author

abayer commented Sep 16, 2016

@svanoort Yeah, I can redo this with TagsAction.

@abayer
Copy link
Member Author

abayer commented Sep 19, 2016

Now properly downstream of jenkinsci/workflow-api-plugin#12

Conflicts:
	src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/Utils.groovy
	src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/BasicModelDefTest.java
@abayer abayer closed this Sep 19, 2016
@abayer abayer reopened this Sep 19, 2016
@abayer
Copy link
Member Author

abayer commented Sep 19, 2016

FYI, current failure on ci.jenkins.io PR build is due to SNAPSHOT check staleness.


package org.jenkinsci.plugins.pipeline.modeldefinition.actions;

public enum SyntheticContext {
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 you meant to remove this, since we don't need the whole Context/ContextAction bit after adding the TagsAction.

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, I meant to leave it - I want an enum of possible values for the SYNTHETIC_STAGE_TAG.

Copy link
Member Author

Choose a reason for hiding this comment

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

..but have now gotten rid of it. yay?

Copy link
Member

Choose a reason for hiding this comment

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

Yay!

*
* @author Andrew Bayer
*/
public class SyntheticStageMarkerAction extends InvisibleAction {
Copy link
Member

Choose a reason for hiding this comment

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

🐛 Not needed now that we can use TagsAction as our marker (and indeed a broader-use marker).

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, forgot to delete that.

* @param context
*/
@Whitelisted
static void markSyntheticStage(String stageName, SyntheticContext context) {
Copy link
Member

Choose a reason for hiding this comment

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

🐛 Better to use static final strings for the markers, i.e. "PRE" and "POST" or similar. Creating an enum just for two values is kind of silly, and if we're just getting string values for 'em we might as well use that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sigh. Ok. =)

assertNull(scanner.findFirstMatch(heads, null, syntheticStagePredicate(SyntheticStageNames.dockerPull(), SyntheticContext.PRE)));
}

private Predicate<FlowNode> syntheticStagePredicate(final String stageName,
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to expose this as part of the public API for Blue Ocean to use with the search/filter workflow APIs?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm betting y'all can write something better. =)

Copy link
Member

Choose a reason for hiding this comment

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

You give people too much credit ;)

@abayer
Copy link
Member Author

abayer commented Sep 19, 2016

@svanoort Ok, switched to Strings. =)

if (currentNode.getAction(TagsAction.class) == null) {
currentNode.actions.add(new TagsAction())
}
currentNode.getAction(TagsAction.class).addTag(SYNTHETIC_STAGE_TAG, context)
Copy link
Member

Choose a reason for hiding this comment

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

This is a hack. Better to have a block-scoped Step which adds this Action using the supported APIs.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is there a way to limit the visibility/exposure of a Step? i.e., can I create one that only can be used in this plugin? If not, then hacks are really the only way I can see to get what we need - a Step that shows up in the snippet generator, etc that does this would be...flawed.

Copy link
Member

Choose a reason for hiding this comment

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

isAdvanced

Copy link
Member

@svanoort svanoort Sep 19, 2016

Choose a reason for hiding this comment

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

Unfortunately I have to disagree with @jglick about the block-scoped step -- it doesn't feel like synthetic stages are truly a different animal than a normal stage. We're just attaching some additional helper information to that stage. Actions are exactly the right thing to use here.

Copy link
Member Author

Choose a reason for hiding this comment

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

I strangely enough agree with @svanoort =)

script.stage(SyntheticStage.dockerPull()) {
Utils.markSyntheticStage(SyntheticStage.dockerPull(), SyntheticStage.SYNTHETIC_PRE)
script.getProperty("docker").image(agent.docker).pull()
}
script.getProperty("docker").image(agent.docker).inside {
Copy link
Member

Choose a reason for hiding this comment

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

BTW more directly written as

script.docker.image…

Copy link
Member Author

Choose a reason for hiding this comment

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

So at least at some point in the past, that very much didn't work. Dunno if it would now, I'll give it a try.

@abayer
Copy link
Member Author

abayer commented Sep 19, 2016

ci.jenkins.io is still...questionable at times. Right now it's barfing due to git user.name and user.email not being set. Fun.

}

private Predicate<FlowNode> syntheticStagePredicate(final String stageName,
final SyntheticContext context) {
final String context) {
return new Predicate<FlowNode>() {
@Override
public boolean apply(FlowNode input) {
return input.getDisplayName().equals(stageName) &&
input.getAction(TagsAction.class) != null &&
Copy link
Member

Choose a reason for hiding this comment

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

🐛 Upon further examination (sorry). Fetching the action 3x is undesirable for performance (sigh). Normally pessimization wouldn't be a bug but I happen to know this one can be fairly costly.

Also worth checking for 'input instanceof StepNode && ((StepNode)input).getDescriptor == WhateverTheStageDescriptorIs' -- faster than string equals since it is a direct memory location compare.

Copy link
Member

Choose a reason for hiding this comment

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

Wait. Nevermind, that's test-only. It would be a bug if it were a public API.

Going to blame that one on still being jetlagged post-JenkinsWorld.

Copy link
Member Author

Choose a reason for hiding this comment

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

Also, I'm specifically trying to compare the displayName to make sure it's the right stage. I did try using StageStartNode, I think it was, whatever you suggested earlier, and it...did not work. At all. So I went back to this. =)

Copy link
Member

Choose a reason for hiding this comment

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

Display name can be the typeDisplayName if there isn't a LabelAction though, so it's not a safe check to be using in general (since you can get false positives). Again, okay in the walled garden of tests, but I wouldn't want to see it elsewhere.

In general, prefer type checks and then a LabelAction (or StageAction) check -- you're putting preconditions first that can be tested quickly. Should be safer and a bit faster (since it'll return negative 99% of the time).

@svanoort
Copy link
Member

In general: the context removal and string changeover look good.

I think this one is 🐝 worthy -- though might suggest using your NotNull/CheckForNull annotations some more.

@abayer
Copy link
Member Author

abayer commented Nov 4, 2016

Closing in favor of #47

@abayer abayer closed this Nov 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants