|
1 | 1 | package pl.allegro.tech.build.axion.release.infrastructure.git;
|
2 | 2 |
|
3 |
| -import org.eclipse.jgit.api.AddCommand; |
4 |
| -import org.eclipse.jgit.api.FetchCommand; |
5 |
| -import org.eclipse.jgit.api.Git; |
6 |
| -import org.eclipse.jgit.api.LogCommand; |
7 |
| -import org.eclipse.jgit.api.PushCommand; |
8 |
| -import org.eclipse.jgit.api.Status; |
| 3 | +import org.eclipse.jgit.api.*; |
9 | 4 | import org.eclipse.jgit.api.errors.GitAPIException;
|
10 | 5 | import org.eclipse.jgit.api.errors.NoHeadException;
|
11 | 6 | import org.eclipse.jgit.diff.DiffFormatter;
|
12 | 7 | import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
13 |
| -import org.eclipse.jgit.lib.AnyObjectId; |
14 |
| -import org.eclipse.jgit.lib.BranchTrackingStatus; |
15 |
| -import org.eclipse.jgit.lib.Config; |
16 |
| -import org.eclipse.jgit.lib.Constants; |
17 |
| -import org.eclipse.jgit.lib.ObjectId; |
18 |
| -import org.eclipse.jgit.lib.Ref; |
19 |
| -import org.eclipse.jgit.lib.Repository; |
20 |
| -import org.eclipse.jgit.lib.StoredConfig; |
| 8 | +import org.eclipse.jgit.lib.*; |
21 | 9 | import org.eclipse.jgit.revwalk.RevCommit;
|
22 | 10 | import org.eclipse.jgit.revwalk.RevSort;
|
23 | 11 | import org.eclipse.jgit.revwalk.RevWalk;
|
24 |
| -import org.eclipse.jgit.transport.PushResult; |
25 |
| -import org.eclipse.jgit.transport.RemoteConfig; |
26 |
| -import org.eclipse.jgit.transport.RemoteRefUpdate; |
27 |
| -import org.eclipse.jgit.transport.TagOpt; |
28 |
| -import org.eclipse.jgit.transport.URIish; |
| 12 | +import org.eclipse.jgit.transport.*; |
29 | 13 | import org.eclipse.jgit.treewalk.filter.PathFilter;
|
30 | 14 | import org.eclipse.jgit.util.SystemReader;
|
31 | 15 | import org.eclipse.jgit.util.io.DisabledOutputStream;
|
32 | 16 | import org.gradle.api.logging.Logger;
|
33 | 17 | import org.gradle.api.logging.Logging;
|
34 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmException; |
35 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmIdentity; |
36 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmPosition; |
37 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmProperties; |
38 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmPushOptions; |
39 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmPushResult; |
40 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmRepository; |
41 |
| -import pl.allegro.tech.build.axion.release.domain.scm.ScmRepositoryUnavailableException; |
42 |
| -import pl.allegro.tech.build.axion.release.domain.scm.TagsOnCommit; |
| 18 | +import pl.allegro.tech.build.axion.release.domain.scm.*; |
43 | 19 |
|
44 | 20 | import java.io.File;
|
45 | 21 | import java.io.IOException;
|
46 | 22 | import java.net.URISyntaxException;
|
47 |
| -import java.util.ArrayList; |
48 |
| -import java.util.HashMap; |
49 |
| -import java.util.List; |
50 |
| -import java.util.Map; |
51 |
| -import java.util.Set; |
52 |
| -import java.util.Optional; |
| 23 | +import java.util.*; |
53 | 24 | import java.util.regex.Pattern;
|
54 | 25 | import java.util.stream.Collectors;
|
55 | 26 | import java.util.stream.StreamSupport;
|
@@ -333,37 +304,72 @@ private void assertPathExists(String path) {
|
333 | 304 | }
|
334 | 305 |
|
335 | 306 | public ScmPosition currentPosition() {
|
| 307 | + String revision = getRevision(); |
| 308 | + String branchName = branchName(); |
| 309 | + boolean isClean = !checkUncommittedChanges(); |
| 310 | + return new ScmPosition(revision, branchName, isClean); |
| 311 | + } |
| 312 | + |
| 313 | + private String getRevision() { |
336 | 314 | try {
|
337 | 315 | String revision = "";
|
338 | 316 | if (hasCommits()) {
|
339 | 317 | ObjectId head = head();
|
340 | 318 | revision = head.name();
|
341 | 319 | }
|
342 |
| - |
343 |
| - boolean isClean = !checkUncommittedChanges(); |
344 |
| - |
345 |
| - String branchName = branchName(); |
346 |
| - return new ScmPosition(revision, branchName, isClean); |
| 320 | + return revision; |
347 | 321 | } catch (IOException e) {
|
348 | 322 | throw new ScmException(e);
|
349 | 323 | }
|
350 | 324 | }
|
351 | 325 |
|
| 326 | + private String branchName() { |
| 327 | + return branchNameFromGithubEnvVariable().orElseGet(this::branchNameFromGit); |
| 328 | + } |
| 329 | + |
352 | 330 | /**
|
353 |
| - * @return branch name or 'HEAD' when in detached state, unless it is overridden by 'overriddenBranchName' |
| 331 | + * <p>If executed within workflow on GitHub Actions and that workflow is triggered by pull_request (or pull_request_target) |
| 332 | + * event, GitHub will not check out the source branch of the PR, but some custom ref: 'refs/pull/<pr_number>/merge' |
| 333 | + * (they call it a "merge branch"). It effectively means that repository is in detached-HEAD state and axion-release |
| 334 | + * is not able to get the branch name from HEAD ref.</p> |
| 335 | + * |
| 336 | + * <p>For pull_request and pull_request_target events, GitHub sets a special environment variable GITHUB_HEAD_REF. |
| 337 | + * It contains the head ref of source branch of the PR which triggered the workflow. This variable is not set |
| 338 | + * for other event types.</p> |
| 339 | + * |
| 340 | + * <p>If the build is not executed on GitHub Actions, this method will always return Optional.empty.</p> |
| 341 | + * |
| 342 | + * @return source branch of the PR which triggered GitHub Actions workflow |
354 | 343 | */
|
355 |
| - private String branchName() throws IOException { |
356 |
| - // this returns HEAD as branch name when in detached state |
357 |
| - Optional<Ref> ref = Optional.ofNullable(jgitRepository.getRepository().exactRef(Constants.HEAD)); |
358 |
| - String branchName = ref.map(r -> r.getTarget().getName()) |
359 |
| - .map(Repository::shortenRefName) |
360 |
| - .orElse(null); |
361 |
| - |
362 |
| - if ("HEAD".equals(branchName) && properties.getOverriddenBranchName() != null && !properties.getOverriddenBranchName().isEmpty()) { |
363 |
| - branchName = Repository.shortenRefName(properties.getOverriddenBranchName()); |
| 344 | + private Optional<String> branchNameFromGithubEnvVariable() { |
| 345 | + if (env("GITHUB_ACTIONS").isPresent()) { |
| 346 | + return env("GITHUB_HEAD_REF"); |
364 | 347 | }
|
| 348 | + return Optional.empty(); |
| 349 | + } |
| 350 | + |
| 351 | + private Optional<String> env(String name) { |
| 352 | + return Optional.ofNullable(System.getenv(name)); |
| 353 | + } |
365 | 354 |
|
366 |
| - return branchName; |
| 355 | + /** |
| 356 | + * @return branch name or 'HEAD' when in detached state, unless it is overridden by 'overriddenBranchName' |
| 357 | + */ |
| 358 | + private String branchNameFromGit() { |
| 359 | + try { |
| 360 | + // this returns HEAD as branch name when in detached state |
| 361 | + Optional<Ref> ref = Optional.ofNullable(jgitRepository.getRepository().exactRef(Constants.HEAD)); |
| 362 | + String branchName = ref.map(r -> r.getTarget().getName()) |
| 363 | + .map(Repository::shortenRefName) |
| 364 | + .orElse(null); |
| 365 | + |
| 366 | + if ("HEAD".equals(branchName) && properties.getOverriddenBranchName() != null && !properties.getOverriddenBranchName().isEmpty()) { |
| 367 | + branchName = Repository.shortenRefName(properties.getOverriddenBranchName()); |
| 368 | + } |
| 369 | + return branchName; |
| 370 | + } catch (IOException e) { |
| 371 | + throw new ScmException(e); |
| 372 | + } |
367 | 373 | }
|
368 | 374 |
|
369 | 375 | @Override
|
|
0 commit comments