Skip to content

Conversation

@rsandell
Copy link
Member

@rsandell rsandell commented Mar 19, 2023

  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests - that demonstrates feature works or fixes the issue

@rsandell
Copy link
Member Author

I had an itch and had to scratch it.
Asking review from some people to check my jolt cola infused hacking high :)

public class StepSelectionConfigurationTest {

@Rule
public RealJenkinsRule r = new RealJenkinsRule().withDebugPort(4001).withDebugServer(false);
Copy link
Member Author

Choose a reason for hiding this comment

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

Can I keep this in the code or do I need to remove it before merging?

Copy link
Member

Choose a reason for hiding this comment

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

using a static port in a test is liklely to cause port conflicts when run on other systems (and random failures). so I would remove it.

@jglick
Copy link
Member

jglick commented Mar 22, 2023

I do not think it makes sense to do something like this in a random plugin. If there is a genuine need to block certain steps from certain folders or the whole controller, that should be done generically. You can also use https://plugins.jenkins.io/extension-filter/ in general.

What is the motivation here? Certain steps in this plugin are known to be bad ideas, and they should simply be deprecated for everyone.

Comment on lines +109 to +134
ExtensionList<StepDescriptor> stepDescriptors = ExtensionList.lookup(StepDescriptor.class);

FilterImpl filter = ExtensionList.lookupSingleton(FilterImpl.class);
Collection<StepDescriptor> definedStepDescriptors = getAllStepDescriptors();
List<StepDescriptor> toRemove = new ArrayList<>();
final List<StepDescriptor> toAdd = new ArrayList<>();
for (StepDescriptor descriptor : definedStepDescriptors) {
if (stepDescriptors.contains(descriptor)) {
if (!filter.allows(StepDescriptor.class, new ExtensionComponent<>(descriptor))) {
toRemove.add(descriptor);
}
} else if (filter.allows(StepDescriptor.class, new ExtensionComponent<>(descriptor))) {
toAdd.add(descriptor);
}
}
stepDescriptors.refresh(new ExtensionComponentSet() {
@Override
public <T> Collection<ExtensionComponent<T>> find(Class<T> type) {
if (type == StepDescriptor.class) {
return toAdd.stream().map(stepDescriptor -> new ExtensionComponent<T>(type.cast(stepDescriptor))).collect(Collectors.toSet());
} else {
return Collections.emptyList();
}
}
});
stepDescriptors.removeAll(toRemove);
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 rather low-level and will result in a cryptic error message about an undefined function. Much better to use https://javadoc.jenkins.io/plugin/workflow-api/org/jenkinsci/plugins/workflow/flow/StepListener.html#notifyOfNewStep(org.jenkinsci.plugins.workflow.steps.Step,org.jenkinsci.plugins.workflow.steps.StepContext) to just fail the step with a polite AbortException.

@daniel-beck
Copy link
Member

I suggest splitting this plugin up into multiple ones, each with one or few steps that make sense to be in the same component, and keeping this plugin as an empty shell with dependencies to all of them. This way, admins can uninstall what they don't want.

@rsandell
Copy link
Member Author

It is not random in the sense that it only filters the steps that are defined in this plugin.
The StepListener approach would still make the steps show up in the Snippetizer and create a FlowNode for it but break the build if called, so that is not very user friendly.
The extension-filter plugin requires knowledge about how pipeline steps and other extension points are implemented which also doesn't provide much user friendlyness. And can give a false sense of security when you for example only want to allow one step; in this implementation you can add just that to the allow list. With the extension-filter approach you would need to exclude all other steps, and then be diligent when upgrading the plugin in case the have been new steps added and make sure to exclude those as well.

Yes some sets of steps could be extracted into new plugins, but due to the goal of this plugin there would always be a hodge podge of random good to have steps where one of them might be interesting for someone while others could be risky.

@jglick
Copy link
Member

jglick commented Apr 26, 2023

It is not random in the sense that it only filters the steps that are defined in this plugin.

Perhaps I should rephrase—there is no precedent for a plugin suppressing the existence of its own steps, and this plugin should not be setting such a precedent. If there is a compelling use case for an administrator to block selected Pipeline steps from being run in any job (and I have yet to hear the explanation for that), then it should be done in a separate generic plugin that offers a list of all Pipeline steps.

(Along similar lines, CloudBees CI includes a Pipeline policy system producing build-time errors under configurable conditions.)

The StepListener approach would still make the steps show up in the Snippetizer

If there are specific steps in this plugin that are known to be problematic for specific reasons, they should be placed in the “advanced/deprecated” section with suitable warnings. Start with the most misguided: #47.

and create a FlowNode for it but break the build if called, so that is not very user friendly.

It would break the build with a clear message, which seems a lot friendlier than having the build throw a cryptic stack trace from DSL about an undefined function.

@jglick
Copy link
Member

jglick commented Jun 29, 2023

Copy link
Member

@jtnord jtnord left a comment

Choose a reason for hiding this comment

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

do we still desire this? should it be closed given existing comments?

* @return The unfiltered list of all {@link StepDescriptor}s defined in this plugin.
*/
public static Collection<StepDescriptor> getAllStepDescriptors() {
Hudson jenkins = Hudson.getInstance();
Copy link
Member

Choose a reason for hiding this comment

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

Hudson :-p

}

public synchronized String getDeny() {
return String.join("\n", deny);
Copy link
Member

Choose a reason for hiding this comment

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

Set<String> steps = ExtensionList.lookup(StepDescriptor.class).stream().map(StepDescriptor::getFunctionName).collect(Collectors.toSet());
assertThat(steps, hasItems(allSteps));

//blacklist something
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
//blacklist something
//deny something

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.

5 participants