// Copyright (C) 2018 GerritForge Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jenkins.plugins.gerrit; import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.common.RevisionInfo; import hudson.EnvVars; import hudson.Extension; import hudson.model.EnvironmentContributor; import hudson.model.ItemGroup; import hudson.model.Job; import hudson.model.TaskListener; import java.io.IOException; import java.net.URISyntaxException; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nonnull; import jenkins.branch.BranchSource; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject; @Extension public class GerritEnvironmentContributor extends EnvironmentContributor { private static final Pattern REF_PATTERN = Pattern.compile("^\\d+\\/(?<changeNum>\\d+)\\/(?<patchSet>\\d+)$"); @Override public void buildEnvironmentFor( @Nonnull Job j, @Nonnull EnvVars envs, @Nonnull TaskListener listener) throws IOException, InterruptedException { ItemGroup jobParent = j.getParent(); if (!(jobParent instanceof WorkflowMultiBranchProject)) { return; } WorkflowMultiBranchProject multiBranchProject = (WorkflowMultiBranchProject) jobParent; List<BranchSource> sources = multiBranchProject.getSources(); if (sources.isEmpty() || !(sources.get(0).getSource() instanceof GerritSCMSource)) { return; } WorkflowJob workflowJob = (WorkflowJob) j; GerritSCMSource gerritSCMSource = (GerritSCMSource) multiBranchProject.getSources().get(0).getSource(); GerritURI gerritURI = gerritSCMSource.getGerritURI(); envs.put("GERRIT_CREDENTIALS_ID", gerritSCMSource.getCredentialsId()); envs.put("GERRIT_PROJECT", gerritURI.getProject()); try { envs.put("GERRIT_API_URL", gerritURI.getApiURI().toString()); } catch (URISyntaxException e) { throw new IOException("Unable to get Gerrit API URL from " + gerritURI, e); } if (Boolean.TRUE.equals(gerritSCMSource.getInsecureHttps())) { envs.put("GERRIT_API_INSECURE_HTTPS", "true"); } String displayName = workflowJob.getDisplayName(); Matcher matcher = REF_PATTERN.matcher(displayName); if (matcher.find()) { int patchSetNum = Integer.parseInt(matcher.group("patchSet")); Optional<ChangeInfo> changeInfo = gerritSCMSource.getChangeInfo(Integer.parseInt(matcher.group("changeNum"))); changeInfo.ifPresent( (change) -> { publishChangeDetails( envs, matcher.group("changeNum"), matcher.group("patchSet"), patchSetNum, change, gerritURI); }); } } private void publishChangeDetails( @Nonnull EnvVars envs, String changeNum, String patchSet, int patchSetNum, ChangeInfo change, GerritURI gerritURI) { envs.put("GERRIT_CHANGE_NUMBER", changeNum); envs.put("GERRIT_PATCHSET_NUMBER", patchSet); envs.put("GERRIT_CHANGE_PRIVATE_STATE", booleanString(change.isPrivate)); envs.put("GERRIT_CHANGE_WIP_STATE", booleanString(change.workInProgress)); envs.put("GERRIT_CHANGE_SUBJECT", change.subject); envs.put("GERRIT_CHANGE_URL", gerritURI.setPath("" + change._number).toASCIIString()); envs.put("GERRIT_BRANCH", change.branch); envs.put("GERRIT_TOPIC", nullToEmpty(change.topic)); envs.put("GERRIT_CHANGE_ID", change.id); Map.Entry<String, RevisionInfo> patchSetInfo = change .revisions .entrySet() .stream() .filter(entry -> entry.getValue()._number == patchSetNum) .findFirst() .get(); envs.put("GERRIT_REFNAME", patchSetInfo.getValue().ref); envs.put("GERRIT_PATCHSET_REVISION", patchSetInfo.getKey()); envs.put("GERRIT_CHANGE_OWNER", change.owner.name + " <" + change.owner.email + ">"); envs.put("GERRIT_CHANGE_OWNER_NAME", change.owner.name); envs.put("GERRIT_CHANGE_OWNER_EMAIL", change.owner.email); AccountInfo uploader = patchSetInfo.getValue().uploader; envs.put("GERRIT_PATCHSET_UPLOADER", uploader.name + " <" + uploader.email + ">"); envs.put("GERRIT_PATCHSET_UPLOADER_NAME", uploader.name); envs.put("GERRIT_PATCHSET_UPLOADER_EMAIL", uploader.email); } private String booleanString(Boolean booleanValue) { return Optional.ofNullable(booleanValue).orElse(Boolean.FALSE).toString(); } private String nullToEmpty(String value) { return Optional.ofNullable(value).orElse(""); } }