Skip to content

Fix Git metadata extraction for multi-branch pipelines#493

Merged
nikita-tkachenko-datadog merged 2 commits into
masterfrom
nikita-tkachenko/fix-git-metadata-extraction
Jan 17, 2025
Merged

Fix Git metadata extraction for multi-branch pipelines#493
nikita-tkachenko-datadog merged 2 commits into
masterfrom
nikita-tkachenko/fix-git-metadata-extraction

Conversation

@nikita-tkachenko-datadog

@nikita-tkachenko-datadog nikita-tkachenko-datadog commented Jan 14, 2025

Copy link
Copy Markdown
Collaborator

Requirements for Contributing to this repository

  • Fill out the template below. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion.
  • The pull request must only fix one issue at the time.
  • The pull request must update the test suite to demonstrate the changed functionality.
  • After you create the pull request, all status checks must be pass before a maintainer reviews your contribution. For more details, please see CONTRIBUTING.

What does this PR do?

Fixes Git metadata extraction for multi-branch pipelines.

A multi-branch pipeline has its definition (aka "pipeline script") stored in a Jenkinsfile in a Git repository.
Each branch may have its own version of the pipeline definition, which is why Jenkins automatically creates a separate pipeline for each branch in the repo.
When such pipeline is executed, the first step is the pipeline definition checkout.
The plugin is notified of the checkout, so after it finishes the plugin fetches Git metadata of the checkout (repo URL, branch, commit, etc) and associates it with the pipeline.

The problem is that in some cases the pipeline definition contains another explicit Git checkout command.
What happens in this case is: Git checkout of the pipeline definition is done, pipeline starts executing, then another Git checkout of a different repo is done as one of the pipeline steps.
In this case we want the pipeline to be associated with the latter checkout.

This PR ensures this (prior to the changes the first checkout had higher priority).
The original pipeline definition checkout is stored in a separate set of tags (prefixed with pipeline.definition.git.*) in case this data is needed (it will also be reported in the original set of tags unless there is another Git checkout inside the pipeline).

Existing Git metadata extraction logic was too convoluted to incorporate the fix, so it has been rewritten.
The most notable changes are:

  • GitMetadata and GitCommitMetadata classes are added that encapsulate repository and commit metadata
  • Source class is added, defining where a specific GitMetadata instance is coming from (possible source are - in the order or increasing priority: Jenkins standard environment variables, pipeline definition Git checkout event, generic Git checkout event, user-provided environment variables)
  • The logic for merging together different sets of Git metadata is defined in GitMetadata#merge and GitCommitMetadata#merge

Description of the Change

Alternate Designs

Possible Drawbacks

Verification Process

Additional Notes

Release Notes

Review checklist (to be filled by reviewers)

  • Feature or bug fix MUST have appropriate tests (unit, integration, etc...)
  • PR title must be written as a CHANGELOG entry (see why)
  • Files changes must correspond to the primary purpose of the PR as described in the title (small unrelated changes should have their own PR)
  • PR must have one changelog/ label attached. If applicable it should have the backward-incompatible label attached.
  • PR should not have do-not-merge/ label attached.
  • If Applicable, issue must have kind/ and severity/ labels attached at least.

@nikita-tkachenko-datadog
nikita-tkachenko-datadog force-pushed the nikita-tkachenko/fix-git-metadata-extraction branch from 0c16536 to 2164691 Compare January 15, 2025 13:41
@nikita-tkachenko-datadog
nikita-tkachenko-datadog force-pushed the nikita-tkachenko/fix-git-metadata-extraction branch from 39b77f7 to 245701f Compare January 15, 2025 16:44
@nikita-tkachenko-datadog
nikita-tkachenko-datadog marked this pull request as ready for review January 16, 2025 09:44

@drodriguezhdez drodriguezhdez left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Dropped some comments

Comment on lines +223 to +224
private static void updateGitData(Run<?, ?> run, Map<String, String> environment) {
GitMetadataAction gitMetadataAction = run.getAction(GitMetadataAction.class);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If I understood correctly, if the pipeline has multiple steps that checkouts code, the final git data will use always the latest one.

I guess this already happened with the previous implementation, but I'm wondering if we need to indicate this somewhere (recommend use a single checkout step per pipeline)?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure if it'd be appropriate to ask the users to restructure their pipelines to accommodate our plugin needs.
The root cause of the problem is that CI Visibility assumes there's a 1-to-1 relationship between pipelines and Git repositories, while for Jenkins this is not the case.
I will mention it in the public docs though, that the last checked out repo has higher priority.

Comment on lines +379 to +385
GitMetadataAction gitMetadataAction = run.getAction(GitMetadataAction.class);
if (gitMetadataAction != null) {
gitMetadata = GitMetadata.merge(gitMetadata, gitMetadataAction.getMetadata());
}

gitMetadata = GitMetadata.merge(gitMetadata, GitUtils.buildGitMetadataWithJenkinsEnvVars(environment));
gitMetadata = GitMetadata.merge(gitMetadata, GitUtils.buildGitMetadataWithUserSuppliedEnvVars(environment));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The GitMetadataAction has been merging all the git info across different steps (SCMCheckout and StepListener). With the last 2 lines, aren't we overriding with the env vars available at BuildListener level? (IIRC there's only one BuildData instance per Run<?,?>)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

BuildData is not persisted anywhere, and is created on demand in several places - not only for CI Visibility traces, but also for the events that the plugin sends.
I agree, however, that if GitMetadataAction is available, it should have precedence over the standard Jenkins variables available to the BuildListener.
I've changed the logic accordingly.

public static final String JENKINS_EXECUTOR_NUMBER = "jenkins.executor.number";
public static final String JENKINS_RESULT = "jenkins.result";
public static final String JENKINS_PLUGIN_VERSION = "jenkins.plugin.version";
public static final String PIPELINE_DEFINITION_GIT = "pipeline.definition.git";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This tag uses the shared namespace pipeline and it's not compatible with other CI providers.
Could we use jenkins.pipeline.definition.git instead to encapsulate this in the jenkins namespace?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agree, updated the tags to have jenkins.pipeline.definition.git prefix

Comment thread src/main/java/org/datadog/jenkins/plugins/datadog/traces/CITags.java Outdated
@nikita-tkachenko-datadog
nikita-tkachenko-datadog merged commit fc2c600 into master Jan 17, 2025
@nikita-tkachenko-datadog
nikita-tkachenko-datadog deleted the nikita-tkachenko/fix-git-metadata-extraction branch January 17, 2025 15:05
@nikita-tkachenko-datadog nikita-tkachenko-datadog added the changelog/Fixed Fixed features results into a bug fix version bump label Jan 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/Fixed Fixed features results into a bug fix version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants