diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketBranchDetail.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketBranchDetail.java new file mode 100644 index 000000000..91b0617dc --- /dev/null +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketBranchDetail.java @@ -0,0 +1,66 @@ +/* + * The MIT License + * + * Copyright (c) 2025, Nikolas Falco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.cloudbees.jenkins.plugins.bitbucket.impl.details; + +import edu.umd.cs.findbugs.annotations.Nullable; +import hudson.model.Actionable; +import hudson.model.Run; +import jenkins.model.details.Detail; +import jenkins.model.details.DetailGroup; +import jenkins.scm.api.SCMDetailGroup; +import jenkins.scm.api.metadata.ObjectMetadataAction; + +public class BitbucketBranchDetail extends Detail { + + public BitbucketBranchDetail(Actionable object) { + super(object); + } + + @Nullable + @Override + public String getIconClassName() { + return "symbol-git-branch-outline plugin-ionicons-api"; + } + + @Nullable + @Override + public String getDisplayName() { + return getObjectMetadataAction().getObjectDisplayName(); + } + + @Override + public String getLink() { + return getObjectMetadataAction().getObjectUrl(); + } + + @Override + public DetailGroup getGroup() { + return SCMDetailGroup.get(); + } + + private ObjectMetadataAction getObjectMetadataAction() { + Run run = (Run) getObject(); + return run.getParent().getAction(ObjectMetadataAction.class); + } +} diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketCommitDetails.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketCommitDetails.java new file mode 100644 index 000000000..219c4ba42 --- /dev/null +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketCommitDetails.java @@ -0,0 +1,101 @@ +/* + * The MIT License + * + * Copyright (c) 2025, Nikolas Falco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.cloudbees.jenkins.plugins.bitbucket.impl.details; + +import com.cloudbees.jenkins.plugins.bitbucket.PullRequestSCMRevision; +import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import hudson.model.Actionable; +import jenkins.model.details.Detail; +import jenkins.model.details.DetailGroup; +import jenkins.plugins.git.AbstractGitSCMSource; +import jenkins.scm.api.SCMDetailGroup; +import jenkins.scm.api.SCMRevision; +import jenkins.scm.api.SCMRevisionAction; + +public class BitbucketCommitDetails extends Detail { + public BitbucketCommitDetails(Actionable object) { + super(object); + } + + @Override + public String getIconClassName() { + return "symbol-git-commit-outline plugin-ionicons-api"; + } + + @Nullable + private String getHash(@CheckForNull SCMRevision revision) { + if (revision != null) { + if (revision instanceof PullRequestSCMRevision prRev) { + revision = prRev.getPull(); + } + if (revision instanceof AbstractGitSCMSource.SCMRevisionImpl scRev) { + return scRev.getHash(); + } + } + return null; + } + + @Override + public String getDisplayName() { + SCMRevision revision = getRevision(); + + String hash = getHash(revision); + if (hash != null) { + return hash.substring(0, 7); + } + + return null; + } + + @Override + public String getLink() { + SCMRevision revision = getRevision(); + + String hash = getHash(revision); + if (hash != null) { +// Run run = (Run) getObject(); +// BitbucketLink repoLink = run.getParent().getAction(BitbucketLink.class); +// return repoLink.getUrl() + "/commits/" + prRev.getPull(); + return new BitbucketRepositoryDetail(getObject()).getLink() + "/commit/" + hash; + } + + return null; + } + + @Override + public DetailGroup getGroup() { + return SCMDetailGroup.get(); + } + + private SCMRevision getRevision() { + SCMRevisionAction scmRevisionAction = getObject().getAction(SCMRevisionAction.class); + + if (scmRevisionAction == null) { + return null; + } + + return scmRevisionAction.getRevision(); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketDetailFactory.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketDetailFactory.java new file mode 100644 index 000000000..f0dd0782e --- /dev/null +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketDetailFactory.java @@ -0,0 +1,79 @@ +/* + * The MIT License + * + * Copyright (c) 2025, Nikolas Falco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.cloudbees.jenkins.plugins.bitbucket.impl.details; + +import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource; +import com.cloudbees.jenkins.plugins.bitbucket.PullRequestSCMRevision; +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Run; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import jenkins.model.details.Detail; +import jenkins.model.details.DetailFactory; +import jenkins.scm.api.SCMRevision; +import jenkins.scm.api.SCMRevisionAction; +import jenkins.scm.api.SCMSource; + +@SuppressWarnings("rawtypes") +@Extension +public final class BitbucketDetailFactory extends DetailFactory { + + @Override + public Class type() { + return Run.class; + } + + @NonNull + @Override + public List createFor(@NonNull Run target) { + SCMSource src = SCMSource.SourceByItem.findSource(target.getParent()); + + // Don't add details for non-Bitbucket SCM sources + if (!(src instanceof BitbucketSCMSource)) { + return Collections.emptyList(); + } + + SCMRevisionAction scmRevisionAction = target.getAction(SCMRevisionAction.class); + + if (scmRevisionAction == null) { + return Collections.emptyList(); + } + + List details = new ArrayList<>(); + SCMRevision revision = scmRevisionAction.getRevision(); + + if (revision instanceof PullRequestSCMRevision) { + details.add(new BitbucketPullRequestDetail(target)); + } else { + details.add(new BitbucketBranchDetail(target)); + } + + details.add(new BitbucketCommitDetails(target)); + details.add(new BitbucketRepositoryDetail(target)); + + return details; + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketPullRequestDetail.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketPullRequestDetail.java new file mode 100644 index 000000000..89c8537b8 --- /dev/null +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketPullRequestDetail.java @@ -0,0 +1,65 @@ +/* + * The MIT License + * + * Copyright (c) 2025, Nikolas Falco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.cloudbees.jenkins.plugins.bitbucket.impl.details; + +import edu.umd.cs.findbugs.annotations.Nullable; +import hudson.model.Actionable; +import hudson.model.Run; +import jenkins.model.details.Detail; +import jenkins.model.details.DetailGroup; +import jenkins.scm.api.SCMDetailGroup; +import jenkins.scm.api.metadata.ObjectMetadataAction; + +public class BitbucketPullRequestDetail extends Detail { + public BitbucketPullRequestDetail(Actionable object) { + super(object); + } + + @Nullable + @Override + public String getIconClassName() { + return "symbol-git-pull-request-outline plugin-ionicons-api"; + } + + @Nullable + @Override + public String getDisplayName() { + return getObjectMetadataAction().getObjectDisplayName(); + } + + @Override + public String getLink() { + return getObjectMetadataAction().getObjectUrl(); + } + + @Override + public DetailGroup getGroup() { + return SCMDetailGroup.get(); + } + + private ObjectMetadataAction getObjectMetadataAction() { + Run run = (Run) getObject(); + return run.getParent().getAction(ObjectMetadataAction.class); + } +} \ No newline at end of file diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketRepositoryDetail.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketRepositoryDetail.java new file mode 100644 index 000000000..e6b1efb39 --- /dev/null +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/details/BitbucketRepositoryDetail.java @@ -0,0 +1,84 @@ +/* + * The MIT License + * + * Copyright (c) 2025, Nikolas Falco + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.cloudbees.jenkins.plugins.bitbucket.impl.details; + +import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource; +import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpointProvider; +import edu.umd.cs.findbugs.annotations.Nullable; +import hudson.model.Actionable; +import hudson.model.Run; +import jenkins.model.details.Detail; +import jenkins.model.details.DetailGroup; +import jenkins.scm.api.SCMDetailGroup; +import jenkins.scm.api.SCMSource; + +public class BitbucketRepositoryDetail extends Detail { + public BitbucketRepositoryDetail(Actionable object) { + super(object); + } + + @Nullable + @Override + public String getIconClassName() { + return "symbol-logo-github plugin-ionicons-api"; + } + + @Nullable + @Override + public String getDisplayName() { + BitbucketSCMSource source = getSCMSource(); + + if (source == null) { + return null; + } + + return source.getRepoOwner() + "/" + source.getRepository(); + } + + @Override + public String getLink() { + BitbucketSCMSource source = getSCMSource(); + + if (source == null) { + return null; + } + + return BitbucketEndpointProvider.lookupEndpoint(source.getServerUrl()).map(endpoint -> endpoint.getRepositoryURL(source.getRepoOwner(), source.getRepository())).orElse(null); + } + + @Override + public DetailGroup getGroup() { + return SCMDetailGroup.get(); + } + + private BitbucketSCMSource getSCMSource() { + SCMSource source = SCMSource.SourceByItem.findSource(((Run) getObject()).getParent()); + + if (source instanceof BitbucketSCMSource bitbucketSource) { + return bitbucketSource; + } + + return null; + } +} \ No newline at end of file