diff --git a/.github/workflows/create_draft_release.yml b/.github/workflows/create_draft_release.yml index 121e6bbd80d9..b52514cb7a06 100644 --- a/.github/workflows/create_draft_release.yml +++ b/.github/workflows/create_draft_release.yml @@ -2,6 +2,10 @@ name: Create draft release on: workflow_dispatch: + inputs: + forced_commit_id: + description: 'Force using artifacts from specific commit? If provided, this will try and use the artifacts from the given commit, regardless of build status' + required: false jobs: create_draft_release: @@ -34,6 +38,7 @@ jobs: run: ./tracer/build.sh DownloadAzurePipelineAndGitlabArtifacts env: TargetBranch: ${{ github.event.ref }} + CommitSha: "${{ github.event.inputs.forced_commit_id }}" - name: "Generate release notes" id: release_notes diff --git a/tracer/build/_build/Build.GitHub.cs b/tracer/build/_build/Build.GitHub.cs index 1576b275325c..a42ac5182445 100644 --- a/tracer/build/_build/Build.GitHub.cs +++ b/tracer/build/_build/Build.GitHub.cs @@ -48,6 +48,9 @@ partial class Build [Parameter("The Pull Request number for GitHub Actions")] readonly int? PullRequestNumber; + [Parameter("The specific commit sha to use", List = false)] + readonly string CommitSha; + [Parameter("The git branch to use", List = false)] readonly string TargetBranch; @@ -490,57 +493,109 @@ await client.Issue.Milestone.Update( BuildArtifact artifact = null; var artifactName = $"{FullVersion}-release-artifacts"; + string commitSha = CommitSha; - Logger.Info($"Checking builds for artifact called: {artifactName}"); - string commitSha = String.Empty; - - // start from the current commit, and keep looking backwards until we find a commit that has a build - // that has successful artifacts. Should only be called from branches with a linear history (i.e. single parent) - // This solves a potential issue where we previously selecting a build by start order, not by the actual - // git commit order. Generally that shouldn't be an issue, but if we manually trigger builds on master - // (which we sometimes do e.g. trying to bisect and issue, or retrying flaky test for coverage reasons), - // then we could end up selecting the wrong build. - const int maxCommitsBack = 20; - for (var i = 0; i < maxCommitsBack; i++) + if (!string.IsNullOrEmpty(CommitSha)) { - commitSha = GitTasks.Git($"log {TargetBranch}~{i} -1 --pretty=%H") - .FirstOrDefault(x => x.Type == OutputType.Std) - .Text; + var foundSha = false; + var maxCommitsBack = 20; + // basic verification, to ensure that the provided commitsha is actually on this branch + for (var i = 0; i < maxCommitsBack; i++) + { + var sha = GitTasks.Git($"log {TargetBranch}~{i} -1 --pretty=%H") + .FirstOrDefault(x => x.Type == OutputType.Std) + .Text; - Logger.Info($"Looking for builds for {commitSha}"); + if (string.Equals(CommitSha, sha, StringComparison.OrdinalIgnoreCase)) + { + // OK, this SHA is definitely on this branch + foundSha = true; + break; + } + } - foreach (var build in builds) + if (!foundSha) { - if (string.Equals(build.SourceVersion, commitSha, StringComparison.OrdinalIgnoreCase)) - { - // Found a build for the commit, so should be successful and have an artifact - if (build.Result != BuildResult.Succeeded && build.Result != BuildResult.PartiallySucceeded) - { - Logger.Error($"::error::The build for commit {commitSha} was not successful. Please retry any failed stages for the build before creating a release"); - throw new Exception("Latest build for branch was not successful. Please retry the build before creating a release"); - } + Logger.Error($"Error: The commit {CommitSha} could not be found in the last {maxCommitsBack} of the branch {TargetBranch}" + + $"Ensure that the commit sha you have provided is correct, and you are running the create_release action from the correct branch"); + throw new Exception($"The commit {CommitSha} could not found in the latest {maxCommitsBack} of target branch {TargetBranch}"); + } - try - { - artifact = await buildHttpClient.GetArtifactAsync( - project: AzureDevopsProjectId, - buildId: build.Id, - artifactName: artifactName); - break; - } - catch (ArtifactNotFoundException) + Logger.Info($"Finding build for commit sha: {CommitSha}"); + var build = builds + .FirstOrDefault(b => string.Equals(b.SourceVersion, CommitSha, StringComparison.OrdinalIgnoreCase)); + if (build is null) + { + throw new Exception($"No builds for commit {CommitSha} found. Please check you have provided the correct SHA, and that there is a build in AzureDevops for the commit"); + } + + try + { + artifact = await buildHttpClient.GetArtifactAsync( + project: AzureDevopsProjectId, + buildId: build.Id, + artifactName: artifactName); + } + catch (ArtifactNotFoundException) + { + Logger.Error($"Error: The build {build.Id} for commit could not find {artifactName} artifact for build {build.Id} for commit {commitSha}. " + + $"Ensure the build has successfully generated artifacts for this commit before creating a release"); + throw; + } + } + else + { + Logger.Info($"Checking builds for artifact called: {artifactName}"); + + // start from the current commit, and keep looking backwards until we find a commit that has a build + // that has successful artifacts. Should only be called from branches with a linear history (i.e. single parent) + // This solves a potential issue where we previously selecting a build by start order, not by the actual + // git commit order. Generally that shouldn't be an issue, but if we manually trigger builds on master + // (which we sometimes do e.g. trying to bisect and issue, or retrying flaky test for coverage reasons), + // then we could end up selecting the wrong build. + const int maxCommitsBack = 20; + for (var i = 0; i < maxCommitsBack; i++) + { + commitSha = GitTasks.Git($"log {TargetBranch}~{i} -1 --pretty=%H") + .FirstOrDefault(x => x.Type == OutputType.Std) + .Text; + + Logger.Info($"Looking for builds for {commitSha}"); + + foreach (var build in builds) + { + if (string.Equals(build.SourceVersion, commitSha, StringComparison.OrdinalIgnoreCase)) { - Logger.Error($"Error: could not find {artifactName} artifact for build {build.Id} for commit {commitSha}. " + - $"Ensure the build has completed successfully for this commit before creating a release"); - throw; + // Found a build for the commit, so should be successful and have an artifact + if (build.Result != BuildResult.Succeeded && build.Result != BuildResult.PartiallySucceeded) + { + Logger.Error($"::error::The build for commit {commitSha} was not successful. Please retry any failed stages for the build before creating a release"); + throw new Exception("Latest build for branch was not successful. Please retry the build before creating a release"); + } + + try + { + artifact = await buildHttpClient.GetArtifactAsync( + project: AzureDevopsProjectId, + buildId: build.Id, + artifactName: artifactName); + + break; + } + catch (ArtifactNotFoundException) + { + Logger.Error($"Error: could not find {artifactName} artifact for build {build.Id} for commit {commitSha}. " + + $"Ensure the build has completed successfully for this commit before creating a release"); + throw; + } } } - } - if (artifact is not null) - { - break; + if (artifact is not null) + { + break; + } } }