-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added release script #64
Changes from all commits
4a1603a
a9f8fb4
c7147d3
b14125b
e2e3a81
1b24a3d
615870d
04247ac
0d8a2c6
ed9c69f
6aa9cfe
ac99ca0
e98c503
28c0054
60e1273
c196c00
7bfa0f5
11a6b76
2153dba
6d9f0c1
ee1ba23
40a072d
888b871
45ba06e
0d47768
c21734c
1a7ce46
65496ae
1317180
8a7ff86
94ce303
adf36aa
b92c618
be67caf
c584737
c13d2e1
7f2a683
de48a04
652d818
f04fa11
9f1d7a3
78e7f9d
1a23627
0d6ebec
bbce35b
0671c82
1445621
d06c5d7
f109b40
4d2bef7
5aa9ac3
067c79e
f7dd634
5d959bf
094ba29
c956cc4
f266b4d
b6e3221
cbc64a4
1ca1c45
55bb60f
da57a40
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
name: "PR Is Mergeable" | ||
description: "Checks whether the provided PR is approved and all status checks either succeeded or have been skipped" | ||
|
||
inputs: | ||
pr-ref: | ||
description: "The reference (i.e. either number or a branch) of the PR to check" | ||
required: true | ||
fail-on-unmergeable: | ||
description: "Whether to fail the action if the PR is not mergeable" | ||
required: false | ||
default: "true" | ||
repo: | ||
description: "The repository of the PR" | ||
required: false | ||
default: ${{ github.repository }} | ||
token: | ||
description: "The GitHub access token (with PR read permissions) to access the PR" | ||
required: false | ||
default: ${{ github.token }} | ||
excluded-check-runs: | ||
description: "A JSON object, where the keys are the names of the workflows to exclude. The values are a list of step names to ignore. If the list is empty, all steps of the workflow will be ignored." | ||
required: false | ||
default: '{\"${{ github.workflow }}\": []}' | ||
|
||
outputs: | ||
pr-number: | ||
description: "The number of the PR that was checked" | ||
value: ${{ steps.check.outputs.PR_NUMBER }} | ||
is-mergeable: | ||
description: "Whether the PR is mergeable" | ||
value: ${{ steps.check.outputs.RESULT }} | ||
|
||
runs: | ||
using: composite | ||
steps: | ||
- name: "Print Action Start" | ||
run: echo ">>>>> Starting PR Is Mergeable Action; Not printing inputs, as they might contain sensitive information" | ||
shell: bash | ||
|
||
- name: "Check Whether PR Is Mergeable" | ||
id: check | ||
run: | | ||
PR_JSON=$(gh pr view "${{ inputs.pr-ref }}" --repo "${{ inputs.repo }}" --json number,mergeable,reviewDecision,statusCheckRollup) | ||
|
||
PR_NUMBER=$(jq -r '.number' <<< "$PR_JSON") | ||
PR_MERGEABLE=$(jq -r '.mergeable' <<< "$PR_JSON") | ||
PR_DECISION=$(jq -r '.reviewDecision' <<< "$PR_JSON") | ||
|
||
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT | ||
echo "[DEBUG] PR #$PR_NUMBER (in ${{ inputs.repo }}) is mergeable: $PR_MERGEABLE with decision $PR_DECISION" | ||
|
||
if [[ "$PR_DECISION" != "APPROVED" ]]; then | ||
echo "PR #$PR_NUMBER (in ${{ inputs.repo }}) has not been approved." | ||
echo "RESULT=false" >> $GITHUB_OUTPUT | ||
exit 0 | ||
fi | ||
|
||
if [[ "$PR_MERGEABLE" != "MERGEABLE" ]]; then | ||
echo "PR #$PR_NUMBER (in ${{ inputs.repo }}) is not mergeable (i.e. there are conflicts)." | ||
echo "RESULT=false" >> $GITHUB_OUTPUT | ||
exit 0 | ||
fi | ||
|
||
PR_CHECKS=$(jq -r '.statusCheckRollup' <<< "$PR_JSON") | ||
|
||
# check runs are things like our CI pipeline | ||
FAILED_CHECK_RUNS=$(jq -r '.[] | select(.__typename == "CheckRun" and .conclusion != "SUCCESS" and .conclusion != "NEUTRAL")' <<< "$PR_CHECKS") | ||
EXCLUDED_WORKFLOWS=$(jq -r 'keys[]' <<< "${{ inputs.excluded-check-runs }}") | ||
|
||
while IFS= read -r EXCLUDED_WORKFLOW; do | ||
if [[ -z "$EXCLUDED_WORKFLOW" ]]; then | ||
continue | ||
fi | ||
if [[ -z "$FAILED_CHECK_RUNS" ]]; then | ||
break | ||
fi | ||
|
||
EXCLUDED_STEPS=$(jq -r --arg workflow "$EXCLUDED_WORKFLOW" '.[$workflow] | .[]' <<< "${{ inputs.excluded-check-runs }}") | ||
|
||
if [[ -z "$EXCLUDED_STEPS" ]]; then | ||
# the provided list is empty, so ignore all steps of the workflow | ||
FAILED_CHECK_RUNS=$(jq -r --arg workflow "$EXCLUDED_WORKFLOW" 'select(.workflowName != $workflow)' <<< "$FAILED_CHECK_RUNS") | ||
else | ||
while IFS= read -r EXCLUDED_STEP; do | ||
if [[ -z "$EXCLUDED_STEP" ]]; then | ||
continue | ||
fi | ||
FAILED_CHECK_RUNS=$(jq -r --arg workflow "$EXCLUDED_WORKFLOW" --arg step "$EXCLUDED_STEP" 'select(.workflowName != $workflow and .name != $step)' <<< "$FAILED_CHECK_RUNS") | ||
done <<< "$EXCLUDED_STEPS" | ||
fi | ||
done <<< "$EXCLUDED_WORKFLOWS" | ||
|
||
if [[ -n "$FAILED_CHECK_RUNS" ]]; then | ||
echo "PR #$PR_NUMBER (in ${{ inputs.repo }}) contains failed check runs: " | ||
echo "$FAILED_CHECK_RUNS" | ||
echo "RESULT=false" >> $GITHUB_OUTPUT | ||
exit 0 | ||
fi | ||
|
||
# context checks are things like the license agreement check | ||
FAILED_CONTEXT_CHECKS=$(jq -r '.[] | select(.__typename == "StatusContext" and .state != "SUCCESS" and .state != "NEUTRAL")' <<< "$PR_CHECKS") | ||
if [[ -n "$FAILED_CONTEXT_CHECKS" ]]; then | ||
echo "PR #$PR_NUMBER (in ${{ inputs.repo }}) contains failed context checks: " | ||
echo "$FAILED_CONTEXT_CHECKS" | ||
echo "RESULT=false" >> $GITHUB_OUTPUT | ||
exit 0 | ||
fi | ||
|
||
echo "RESULT=true" >> $GITHUB_OUTPUT | ||
shell: bash | ||
env: | ||
GH_TOKEN: ${{ inputs.token }} | ||
|
||
- name: "Fail If PR Is Not Mergeable" | ||
if: ${{ inputs.fail-on-unmergeable == 'true' && steps.check.outputs.RESULT != 'true' }} | ||
run: exit 1 | ||
shell: bash | ||
|
||
- name: "Print Action End" | ||
if: always() | ||
run: echo "<<<<< Finished PR Is Mergeable Action" | ||
shell: bash |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
name: "Workflow Succeeded" | ||
description: "Checks whether the latest run of a given workflow for a given commit SHA succeeded" | ||
|
||
inputs: | ||
workflow: | ||
description: "The name of the workflow to check" | ||
required: true | ||
sha: | ||
description: "The commit SHA to check the workflow for" | ||
required: true | ||
repo: | ||
description: "The repository of the workflow" | ||
required: false | ||
default: ${{ github.repository }} | ||
token: | ||
description: "The GitHub access token (with workflow read permissions) to access the workflow" | ||
required: false | ||
default: ${{ github.token }} | ||
excluded-jobs: | ||
description: "A JSON list of job names to ignore" | ||
required: false | ||
default: '[]' | ||
outputs: | ||
run-id: | ||
description: "The ID of the latest run of the workflow" | ||
value: ${{ steps.find-run-id.outputs.RUN_ID }} | ||
succeeded: | ||
description: "Whether the latest run of the workflow succeeded" | ||
value: ${{ steps.set-result.outputs.RESULT }} | ||
|
||
runs: | ||
using: composite | ||
steps: | ||
- name: "Print Action Start" | ||
run: echo ">>>>> Starting Workflow Succeeded Action; Not printing inputs, as they might contain sensitive information" | ||
shell: bash | ||
|
||
- name: "Determine Run Id" | ||
id: find-run-id | ||
run: | | ||
RUN_JSON=$(gh run list --commit "${{ inputs.sha }}" --workflow "${{ inputs.workflow }}" --repo "${{ inputs.repo }}" --status completed --limit 1 --json databaseId,conclusion | jq '.[0]') | ||
|
||
if [[ "$(jq -r '.conclusion' <<< "$RUN_JSON")" != "success" ]]; then | ||
exit 1 | ||
fi | ||
|
||
echo "RUN_ID=$(jq -r '.databaseId' <<< "$RUN_JSON")" >> $GITHUB_OUTPUT | ||
shell: bash | ||
env: | ||
GH_TOKEN: ${{ inputs.token }} | ||
|
||
- name: "Check Run Jobs" | ||
id: check-run-jobs | ||
run: | | ||
JOBS_JSON=$(gh run view "${{ steps.find-run-id.outputs.RUN_ID }}" --json jobs) | ||
NON_SUCCESSFUL_JOBS=$(jq -r '.jobs[] | select(.conclusion != "success" and .conclusion != "neutral")' <<< "$JOBS_JSON") | ||
EXCLUDED_JOBS=$(jq -r '.[]' <<< "${{ inputs.excluded-jobs }}") | ||
while IFS= read -r EXCLUDED_JOB; do | ||
if [[ -z "$EXCLUDED_JOB" ]]; then | ||
continue | ||
fi | ||
NON_SUCCESSFUL_JOBS=$(jq -r --arg name "$EXCLUDED_JOB" 'select(.name != $name)' <<< "$NON_SUCCESSFUL_JOBS") | ||
done <<< "$EXCLUDED_JOBS" | ||
|
||
if [[ -n "$NON_SUCCESSFUL_JOBS" ]]; then | ||
echo "The following jobs did not succeed:" | ||
echo "$NON_SUCCESSFUL_JOBS" | ||
exit 1 | ||
fi | ||
shell: bash | ||
env: | ||
GH_TOKEN: ${{ inputs.token }} | ||
|
||
- name: "Set Result" | ||
if: always() | ||
id: set-result | ||
run: | | ||
if [[ "${{ steps.find-run-id.outcome }}" != "success" ]]; then | ||
echo "RESULT=false" >> $GITHUB_OUTPUT | ||
exit 0 | ||
fi | ||
|
||
if [[ "${{ steps.check-run-jobs.outcome }}" != "success" ]]; then | ||
echo "RESULT=false" >> $GITHUB_OUTPUT | ||
exit 0 | ||
fi | ||
|
||
echo "RESULT=true" >> $GITHUB_OUTPUT | ||
shell: bash | ||
|
||
- name: "Print Action End" | ||
if: always() | ||
run: echo "<<<<< Finished Workflow Succeeded Action" | ||
shell: bash |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
name: "Perform Release" | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
release_pr_number: | ||
description: "The PR number of the release PR" | ||
required: true | ||
skip-pr-merge: | ||
description: "Whether to skip merging the PRs" | ||
required: false | ||
default: false | ||
type: boolean | ||
|
||
env: | ||
MVN_CLI_ARGS: --batch-mode --no-transfer-progress --fail-at-end --show-version -DskipTests | ||
JAVA_VERSION: 17 | ||
|
||
jobs: | ||
prerequisites: | ||
name: "Prerequisites" | ||
outputs: | ||
release-version: ${{ steps.determine-branch-names.outputs.RELEASE_VERSION }} | ||
release-tag: ${{ steps.determine-branch-names.outputs.RELEASE_TAG }} | ||
code-branch: ${{ steps.determine-branch-names.outputs.CODE_BRANCH_NAME }} | ||
release-commit: ${{ steps.determine-branch-names.outputs.RELEASE_COMMIT }} | ||
permissions: | ||
pull-requests: read | ||
contents: read | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: "Determine Branch Names" | ||
id: determine-branch-names | ||
run: | | ||
if [[ "${{ github.event_name }}" == "pull_request_review" ]]; then | ||
echo "[DEBUG] Taking branch name from pull request event" | ||
BRANCH_NAME=${{ github.event.pull_request.head.ref }} | ||
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | ||
echo "[DEBUG] Taking branch name from workflow dispatch event" | ||
BRANCH_NAME=$(gh pr view ${{ github.event.inputs.release_pr_number }} --repo "${{ github.repository }}" --json headRefName | jq -r '.headRefName') | ||
else | ||
echo "Cannot determine branch name from event '${{ github.event_name }}'" | ||
exit 1 | ||
fi | ||
|
||
RELEASE_VERSION=$(echo "$BRANCH_NAME" | cut -d '-' -f2) | ||
|
||
echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_OUTPUT | ||
echo "RELEASE_TAG=rel/$RELEASE_VERSION" >> $GITHUB_OUTPUT | ||
echo "CODE_BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT | ||
echo "RELEASE_COMMIT=$(gh release view "$RELEASE_TAG" --repo "${{ github.repository }}" --json targetCommitish | jq -r '.targetCommitish')" >> $GITHUB_OUTPUT | ||
|
||
echo "[DEBUG] Current GITHUB_OUTPUT: '$(cat $GITHUB_OUTPUT)'" | ||
env: | ||
GH_TOKEN: ${{ github.token }} | ||
|
||
- name: "Checkout Repository" | ||
uses: actions/checkout@v4 | ||
|
||
- name: "Check Whether Code PR Can Be Merged" | ||
if: ${{ inputs.skip-pr-merge != 'true' }} | ||
uses: ./.github/actions/pr-is-mergeable | ||
with: | ||
pr-ref: ${{ steps.determine-branch-names.outputs.CODE_BRANCH_NAME }} | ||
excluded-check-runs: | | ||
{ | ||
\"Continuous Integration\": [\"Run BlackDuck Scan\", \"Run Security Rating\"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Minor/Question) This is a leftover from copying right? We don't use Blackduck in this repo, AFAIK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do believe the |
||
\"dependabot merger\": [] | ||
} | ||
|
||
- name: "Check Code Release Commit Continuous Integration" | ||
if: ${{ inputs.skip-pr-merge != 'true' }} | ||
uses: ./.github/actions/workflow-succeeded | ||
with: | ||
workflow: "Continuous Integration" | ||
sha: ${{ steps.determine-branch-names.outputs.RELEASE_COMMIT }} | ||
|
||
release: | ||
name: "Release" | ||
needs: [ prerequisites ] | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write # needed to modify the release draft | ||
pull-requests: write # needed to merge the release PR | ||
steps: | ||
- name: "Setup java" | ||
uses: actions/setup-java@v4 | ||
with: | ||
distribution: "sapmachine" | ||
java-version: ${{ env.JAVA_VERSION }} | ||
server-id: ossrh | ||
server-username: MAVEN_CENTRAL_USER # env variable for username in deploy | ||
server-password: MAVEN_CENTRAL_PASSWORD # env variable for token in deploy | ||
|
||
- name: "Download Release Asset" | ||
id: download-asset | ||
run: | | ||
gh release download ${{ needs.prerequisites.outputs.release-tag }} --dir ./ --repo "${{ github.repository }}" | ||
# x=extract v=verbose z=decompress f=file C=destination directory | ||
tar -xvzf release-artifacts.tar.gz -C . | ||
env: | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: "Import GPG Key" | ||
run: | | ||
echo "${{ secrets.PGP_PRIVATE_KEY }}" | gpg --batch --passphrase "$PASSPHRASE" --import | ||
env: | ||
PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} | ||
|
||
- name: "Deploy Locally" | ||
run: > | ||
mvn | ||
$MVN_CLI_ARGS | ||
-DaltDeploymentRepository=local::file:./temp_local_repo | ||
-Drelease | ||
deploy | ||
env: | ||
MAVEN_CENTRAL_USER: ${{ secrets.MAVEN_CENTRAL_USER }} | ||
MAVEN_GPG_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} | ||
|
||
- name: "Deploy Staging" | ||
run: | | ||
# Create an empty directory to correctly execute the plugin | ||
mkdir temp | ||
cd temp | ||
MVN_ARGS="$MVN_CLI_ARGS org.sonatype.plugins:nexus-staging-maven-plugin:1.7.0:deploy-staged-repository -DserverId=ossrh -DnexusUrl=https://oss.sonatype.org -DrepositoryDirectory=../temp_local_repo -DstagingProfileId=$MAVEN_CENTRAL_PROFILE_ID" | ||
newtork marked this conversation as resolved.
Show resolved
Hide resolved
|
||
mvn $MVN_ARGS | ||
env: | ||
MAVEN_CENTRAL_USER: ${{ secrets.SONATYPE_TOKEN_NAME }} | ||
MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_TOKEN_PASS }} | ||
MAVEN_CENTRAL_PROFILE_ID: ${{ secrets.MAVEN_CENTRAL_PROFILE_ID }} | ||
|
||
- name: "Merge Code PR" | ||
if: ${{ inputs.skip-pr-merge != 'true' }} | ||
run: gh pr merge --squash "${{ needs.prerequisites.outputs.code-branch }}" --delete-branch --repo "${{ github.repository }}" | ||
env: | ||
GH_TOKEN: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }} | ||
|
||
- name: "Publish the Draft Release" | ||
run: gh release edit ${{ needs.prerequisites.outputs.release-tag }} --draft=false --repo "${{ github.repository }}" | ||
env: | ||
GH_TOKEN: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Question)
Doesn't this mean by default "all steps of workflow ${{ github.workflow }}" will be ignored? This doesn't have an effect on the action? Wouldn't default "{}" better fit, i.e. to not ignore anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole file is unreadable. If it was approved for the Cloud SDK we can also approve it of the AI SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought you had higher standards for AI SDK (than Cloud SDK) 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the whole generation of pom files with plugins script. Maybe we get rid of this in 2030 😁