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

Manifest Generation Improvements #179

Merged
merged 27 commits into from
Jan 18, 2021
Merged

Manifest Generation Improvements #179

merged 27 commits into from
Jan 18, 2021

Conversation

sghill
Copy link

@sghill sghill commented Jan 13, 2021

This change aims to be backwards-compatible while fixing up-to-date tracking for manifest generation, improving task configuration avoidance, and leveraging lazy configuration. It lays the groundwork for eventually supporting configuration cache and moves the implementation toward Kotlin. Finally, it deprecates several classes, methods, and fields that will be removed in v1.0.0.

It's a goal of this work to change the implementation without meaningfully changing the output. Any fields that may be different from a maven-hpi-plugin run should be addressed in a different change.

Task Configuration Avoidance/Incremental Build

Jenkins manifest generation is complex. This plugin generates two useful manifests -- jpi and hpl.

Jpi Manifest

The jpi manifest has over a dozen entries that are either quite expensive, or very cheap to produce. To better reflect this, several new tasks have been introduced.

generateJenkinsPluginClassManifest

This task produces an intermediate manifest with only the Plugin-Class entry. It needs to look through all outputs of the main source set for a sole subclass of hudson.Plugin. Any change to the main source set requires this task to be re-run.

The Jenkins project now prefers using @Extension annotations instead, but this remains for backwards-compatibility.

generateJenkinsPluginDependenciesManifest

This task produces an intermediate manifest with only the Plugin-Dependencies entry. This value is calculated from the existing DependencyAnalysis classes, but a temporary Java bridge has been introduced to make this value accessible from the Kotlin code.

To support up-to-date tracking, this task considers artifacts that meet all the following criteria as inputs:

  • from resolvable configurations
  • from LibraryElements=jpi configurations
  • from configurations that do not start with serverRuntime (else cyclical task dependency)
  • from configurations that do not start with testRuntime (else cyclical task dependency)

It's necessary to not hardcode the supported configurations, because any registered feature variant is included as an optional plugin dependency.

Unfortunately the files alone are not enough to construct the Plugin-Dependencies format, so the actual task execution still calls back to the project. This currently prevents configuration caching from working. A @PendingFeature spec is in the codebase that tests this condition.

generateJenkinsSupportDynamicLoadingManifest

This task produces an intermediate manifest with only the Support-Dynamic-Loading entry. The value is determined by building a sezpoz index of the main source set and aggregating the @Extension#dynamicLoadable values of everything found. Any change to the main source set requires this task to be re-run.

generateJenkinsManifest

This task produces the final jpi manifest that is consumed by the jar and jpi. It models everything else, including the three intermediate manifests from above, as inputs so it is re-run when required.

One oddity to be aware of is if your project version ends in -SNAPSHOT, the plugin appends a timestamp. This causes this task, and downstream tasks, to be out-of-date all the time. I'd recommend using something like nebula.release's devSnapshot task instead of the built-in behavior. I'm considering removing the timestamp behavior, or making it opt-in, by v1.0.0.

Hpl Manifest

This manifest builds on the jpi manifest, adding the Libraries and Resource-Path entries.

Previously this was modeled as a subclass that took a constructor argument of Project.

Now the generated jpi manifest is considered an input to the GenerateHplTask, which will cause the hpl to be regenerated whenever the upstream manifest changes. Additionally, by not using the Project class at execution time, we move closer towards supporting the configuration cache.

Lazy Configuration

This change favors using lazy properties in JpiExtension while also retaining backwards compatibility. Several tests have been added for populating nested closures with assignments and method calls. So far it hasn't seemed necessary to deprecate many of these extension methods.

Deprecations

  • org.jenkinsci.gradle.plugins.jpi.JpiExtension#developers
  • org.jenkinsci.gradle.plugins.jpi.JpiExtension.Developers
  • org.jenkinsci.gradle.plugins.jpi.JpiExtension#mainSourceTree
  • org.jenkinsci.gradle.plugins.jpi.JpiExtension#testSourceTree
  • org.jenkinsci.gradle.plugins.jpi.JpiManifest
  • org.jenkinsci.gradle.plugins.jpi.JpiHplManifest
  • configureManifest task

Fixes JENKINS-58205.
Closes #178.

sghill added 25 commits January 8, 2021 12:09
This breaks out the Plugin-Class population into its own task that
generates a dedicated manifest file. Rather than having a subclass
of Manifest be responsible for scanning the classesDirs and
populating a field, we'll move toward generating separate manifests and
combining them just before the jar and jpi are created.

This is part of the work to better model inputs of the manifest and
support the new configuration cache.

JENKINS-58205
After some thought it seems simplest to break the most complicated parts
of manifest generation into their own tasks and later combine them.
Renaming since this approach is more about the manifest than the legacy
entry of Plugin-Class.

JENKINS-58205
This breaks out the need for sezpoz annotation scanning into its own
task. The manifest is also required in generation of the test hpl and
the Jenkins server hpl. Task dependencies are set up using Gradle's
automatic linkage between task outputs and task inputs.

JENKINS-58205
Populate Libraries within GenerateHplTask from a
ConfigurableFileCollection Classpath Input.

Deprecate the currently unused JpiExtension#mainSourceTree() and
JpiExtension#testSourceTree(). The sourcesets are already available on
the project.

JENKINS-58205
Aggregates the other partial manifest generation tasks and adds Group-Id

JENKINS-58205
This respects the current behavior of appending a timestamp to versions
that end in -SNAPSHOT, but it means that the task is frequently
out-of-date. Prior to 1.0.0, it should be determined whether this plugin
providing partial version calculation is beneficial, given that it means
all downstream tasks are always invalidated and many other plugins exist
for gradle versioning.

JENKINS-58205
JpiManifest is now deprecated and unused anywhere within the codebase.
The configureManifest task no longer depends on the JpiManifest class.
Backwards compatibility is retained by manually defined setId, id,
setEmail, email, setName, name methods. While the pom pulls from more
fields, these three are the only fields used in the manifest.

JENKINS-58205
* Tests for up-to-date checks of tasks.
* Plugin-Dependencies relies on plugins added to a number of dynamic
  configurations, but still uses the #analyse() function to determine
  the plugin dependencies. It's too difficult to do this from just a
  fileset.
* Update the merge logic to not end up with duplicate Manifest-Version
  properties.
* Deprecate configureManifest task

JENKINS-58205
This support was added in Gradle 6.7

JENKINS-58205
@sghill sghill added this to the 0.42.0 milestone Jan 13, 2021
@sghill sghill mentioned this pull request Jan 13, 2021
@sghill
Copy link
Author

sghill commented Jan 13, 2021

I published this as 0.42.0-SNAPSHOT and found that it's also fixing a task dependency issue.

In v0.41.0 and earlier this will not cause the main source set to compile:

$ ./gradlew server

After these changes, compilation happens if necessary.

@sghill sghill merged commit 7bb1a5f into master Jan 18, 2021
@sghill sghill deleted the JENKINS-58205 branch January 18, 2021 00:31
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.

1 participant