-
Notifications
You must be signed in to change notification settings - Fork 4k
[ci] improve experience with optional GitHub workflows #3740
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
Changes from 17 commits
04111bd
c8c3e47
371922c
49b1a87
581711c
1cb0606
d518ed0
84c28aa
57358c8
353d669
f633d7e
0f6225c
30c2f42
cccefa7
0592a12
7bae9fc
3203b95
67c57b6
84a6394
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,46 @@ | ||
| #!/bin/bash | ||
| # | ||
| # [description] | ||
| # Update comment appending a given body to the specified original comment. | ||
| # | ||
| # [usage] | ||
| # append_comment.sh <COMMENT_ID> <BODY> | ||
| # | ||
| # COMMENT_ID: ID of comment that should be modified. | ||
| # | ||
| # BODY: Text that will be appended to the original comment body. | ||
|
|
||
| set -e | ||
|
|
||
| if [ -z "$GITHUB_ACTIONS" ]; then | ||
| echo "Must be run inside GitHub Actions CI" | ||
| exit -1 | ||
| fi | ||
|
|
||
| if [ $# -ne 2 ]; then | ||
| echo "Usage: $0 <COMMENT_ID> <BODY>" | ||
| exit -1 | ||
| fi | ||
|
|
||
| comment_id=$1 | ||
| body=$2 | ||
|
|
||
| old_comment_body=$(curl -sL \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Authorization: token $SECRETS_WORKFLOW" \ | ||
| "${GITHUB_API_URL}/repos/microsoft/LightGBM/issues/comments/$comment_id" | \ | ||
| jq '.body') | ||
| body=${body/failure/failure ❌} | ||
| body=${body/error/failure ❌} | ||
| body=${body/cancelled/failure ❌} | ||
| body=${body/timed_out/failure ❌} | ||
| body=${body/success/success ✔️} | ||
| data=$(jq -n \ | ||
| --argjson body "${old_comment_body%?}\r\n\r\n$body\"" \ | ||
| '{"body":$body}') | ||
StrikerRUS marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| curl -sL \ | ||
| -X PATCH \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Authorization: token $SECRETS_WORKFLOW" \ | ||
| -d "$data" \ | ||
| "${GITHUB_API_URL}/repos/microsoft/LightGBM/issues/comments/$comment_id" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # coding: utf-8 | ||
| import json | ||
| from os import environ | ||
| from sys import argv, exit | ||
| from time import sleep | ||
| try: | ||
| from urllib import request | ||
| except ImportError: | ||
| import urllib2 as request | ||
|
Comment on lines
+7
to
+10
Collaborator
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. why was this necessary? I have a lot more experience with
Collaborator
Author
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. This is for Python 2/3 compatibility. For the same reason I'm not using
Collaborator
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. ok I see, thanks. Fine with me |
||
|
|
||
|
|
||
| def get_runs(workflow_name): | ||
| pr_runs = [] | ||
| if environ.get("GITHUB_EVENT_NAME", "") == "pull_request": | ||
| pr_number = int(environ.get("GITHUB_REF").split('/')[-2]) | ||
| req = request.Request(url="{}/repos/microsoft/LightGBM/issues/{}/comments".format(environ.get("GITHUB_API_URL"), | ||
| pr_number), | ||
| headers={"Accept": "application/vnd.github.v3+json"}) | ||
| url = request.urlopen(req) | ||
| data = json.loads(url.read().decode('utf-8')) | ||
| url.close() | ||
| pr_runs = [i for i in data | ||
| if i['author_association'].lower() in {'owner', 'member', 'collaborator'} | ||
| and i['body'].startswith('/gha run') | ||
| and 'Workflow **{}** has been triggered!'.format(workflow_name) in i['body']] | ||
| return pr_runs[::-1] | ||
|
|
||
|
|
||
| def get_status(runs): | ||
| status = 'success' | ||
| for run in runs: | ||
| body = run['body'] | ||
| if "Status: " in body: | ||
| if "Status: skipped" in body: | ||
| continue | ||
| if "Status: failure" in body: | ||
| status = 'failure' | ||
| break | ||
| if "Status: success" in body: | ||
| status = 'success' | ||
| break | ||
| else: # in progress | ||
| status = 'rerun' | ||
| break | ||
| return status | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| workflow_name = argv[1] | ||
| while True: | ||
| status = get_status(get_runs(workflow_name)) | ||
| if status != 'rerun': | ||
| break | ||
| sleep(60) | ||
| if status == 'failure': | ||
| exit(1) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/bin/bash | ||
| # | ||
| # [description] | ||
| # Rerun specified workflow for given pull request. | ||
| # | ||
| # [usage] | ||
| # rerun_workflow.sh <WORKFLOW_ID> <PR_NUMBER> <PR_BRANCH> | ||
| # | ||
| # WORKFLOW_ID: Identifier (config name of ID) of a workflow to be rerun. | ||
| # | ||
| # PR_NUMBER: Number of pull request for which workflow should be rerun. | ||
| # | ||
| # PR_BRANCH: Name of pull request's branch. | ||
|
|
||
| set -e | ||
|
|
||
| if [ -z "$GITHUB_ACTIONS" ]; then | ||
| echo "Must be run inside GitHub Actions CI" | ||
| exit -1 | ||
| fi | ||
|
|
||
| if [ $# -ne 3 ]; then | ||
| echo "Usage: $0 <WORKFLOW_ID> <PR_NUMBER> <PR_BRANCH>" | ||
| exit -1 | ||
| fi | ||
|
|
||
| workflow_id=$1 | ||
| pr_number=$2 | ||
| pr_branch=$3 | ||
|
|
||
| runs=$(curl -sL \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Authorization: token $SECRETS_WORKFLOW" \ | ||
| "${GITHUB_API_URL}/repos/microsoft/LightGBM/actions/workflows/${workflow_id}/runs?event=pull_request&branch=${pr_branch}" | \ | ||
| jq '.workflow_runs') | ||
| runs=$(echo $runs | jq --arg pr_number "$pr_number" --arg pr_branch "$pr_branch" 'map(select(.event == "pull_request" and ((.pull_requests | length) != 0 and (.pull_requests[0].number | tostring) == $pr_number or .head_branch == $pr_branch)))') | ||
| runs=$(echo $runs | jq 'sort_by(.run_number) | reverse') | ||
|
|
||
| if [[ $(echo $runs | jq 'length') -gt 0 ]]; then | ||
| curl -sL \ | ||
| -X POST \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Authorization: token $SECRETS_WORKFLOW" \ | ||
| "${GITHUB_API_URL}/repos/microsoft/LightGBM/actions/runs/$(echo $runs | jq '.[0].id')/rerun" | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #!/bin/bash | ||
| # | ||
| # [description] | ||
| # Set a status with a given name to the specified commit. | ||
| # | ||
| # [usage] | ||
| # set_commit_status.sh <NAME> <STATUS> <SHA> | ||
| # | ||
| # NAME: Name of status. | ||
| # Status with existing name overwrites a previous one. | ||
| # | ||
| # STATUS: Status to be set. | ||
| # Can be "error", "failure", "pending" or "success". | ||
| # | ||
| # SHA: SHA of a commit to set a status on. | ||
|
|
||
| set -e | ||
|
|
||
| if [ -z "$GITHUB_ACTIONS" ]; then | ||
| echo "Must be run inside GitHub Actions CI" | ||
| exit -1 | ||
| fi | ||
|
|
||
| if [ $# -ne 3 ]; then | ||
| echo "Usage: $0 <NAME> <STATUS> <SHA>" | ||
| exit -1 | ||
| fi | ||
|
|
||
| name=$1 | ||
|
|
||
| status=$2 | ||
| status=${status/error/failure} | ||
| status=${status/cancelled/failure} | ||
| status=${status/timed_out/failure} | ||
| status=${status/in_progress/pending} | ||
| status=${status/queued/pending} | ||
|
|
||
| sha=$3 | ||
|
|
||
| data=$(jq -n \ | ||
| --arg state $status \ | ||
| --arg url "${GITHUB_SERVER_URL}/microsoft/LightGBM/actions/runs/${GITHUB_RUN_ID}" \ | ||
| --arg name "$name" \ | ||
| '{"state":$state,"target_url":$url,"context":$name}') | ||
|
|
||
| curl -sL \ | ||
| -X POST \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Authorization: token $SECRETS_WORKFLOW" \ | ||
| -d "$data" \ | ||
| "${GITHUB_API_URL}/repos/microsoft/LightGBM/statuses/$sha" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| #!/bin/bash | ||
| # | ||
| # [description] | ||
| # Trigger manual workflow run by a dispatch event. | ||
| # | ||
| # [usage] | ||
| # trigger_dispatch_run.sh <PR_URL> <COMMENT_ID> <DISPATCH_NAME> | ||
| # | ||
| # PR_URL: URL of pull request from which dispatch is triggering. | ||
| # | ||
| # COMMENT_ID: ID of comment that is triggering a dispatch. | ||
| # | ||
| # DISPATCH_NAME: Name of a dispatch to be triggered. | ||
|
|
||
| set -e | ||
|
|
||
| if [ -z "$GITHUB_ACTIONS" ]; then | ||
| echo "Must be run inside GitHub Actions CI" | ||
| exit -1 | ||
| fi | ||
|
|
||
| if [ $# -ne 3 ]; then | ||
| echo "Usage: $0 <PR_URL> <COMMENT_ID> <DISPATCH_NAME>" | ||
| exit -1 | ||
| fi | ||
|
|
||
| pr_url=$1 | ||
| comment_id=$2 | ||
| dispatch_name=$3 | ||
|
|
||
| pr=$(curl -sL \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Authorization: token $SECRETS_WORKFLOW" \ | ||
| "$pr_url") | ||
| data=$(jq -n \ | ||
| --arg event_type "$dispatch_name" \ | ||
| --arg pr_number "$(echo $pr | jq '.number')" \ | ||
| --arg pr_sha "$(echo $pr | jq '.head.sha')" \ | ||
| --arg pr_branch "$(echo $pr | jq '.head.ref')" \ | ||
| --arg comment_number "$comment_id" \ | ||
| '{"event_type":$event_type,"client_payload":{"pr_number":$pr_number,"pr_sha":$pr_sha,"pr_branch":$pr_branch,"comment_number":$comment_number}}') | ||
| curl -sL \ | ||
| -X POST \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Authorization: token $SECRETS_WORKFLOW" \ | ||
| -d "$data" \ | ||
| "${GITHUB_API_URL}/repos/microsoft/LightGBM/dispatches" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| name: Optional checks | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: | ||
| - master | ||
|
|
||
| jobs: | ||
| all-successful: | ||
| timeout-minutes: 120 | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/[email protected] | ||
| with: | ||
| fetch-depth: 5 | ||
| submodules: false | ||
| - name: Check that all tests succeeded | ||
| run: | | ||
| workflows=("R valgrind tests") | ||
|
Collaborator
Author
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. Here we should add optional workflows which failures should block PR merging. |
||
| for i in "${workflows[@]}"; do | ||
| python "$GITHUB_WORKSPACE/.ci/get_workflow_status.py" "$i" \ | ||
| || { echo "The last reported status from workflow \"$i\" is failure. Commit fixes and rerun the workflow."; \ | ||
| exit -1; } | ||
| done | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,39 @@ | ||
| name: R artifact builds | ||
|
|
||
| on: | ||
| pull_request_review_comment: | ||
| types: [created] | ||
| repository_dispatch: | ||
| types: [gha_run_build_r_artifacts] | ||
|
|
||
| jobs: | ||
| cran-package: | ||
| name: cran-package | ||
| if: github.event.comment.body == '/gha build r-artifacts' && contains('OWNER,MEMBER,COLLABORATOR', github.event.comment.author_association) | ||
| timeout-minutes: 60 | ||
| runs-on: ubuntu-latest | ||
| container: rocker/r-base | ||
| env: | ||
| SECRETS_WORKFLOW: ${{ secrets.WORKFLOW }} | ||
| steps: | ||
| - name: Install Git before checkout | ||
| - name: Install essential software before checkout | ||
| shell: bash | ||
| run: | | ||
| apt-get update | ||
| apt-get install --no-install-recommends -y git | ||
| apt-get install --no-install-recommends -y \ | ||
| curl \ | ||
| git \ | ||
| jq | ||
| - name: Checkout repository | ||
| uses: actions/[email protected] | ||
| with: | ||
| fetch-depth: 5 | ||
| submodules: true | ||
| repository: microsoft/LightGBM | ||
| ref: "refs/pull/${{ github.event.client_payload.pr_number }}/merge" | ||
| - name: Send init status | ||
| if: ${{ always() }} | ||
| run: | | ||
| $GITHUB_WORKSPACE/.ci/append_comment.sh \ | ||
| "${{ github.event.client_payload.comment_number }}" \ | ||
| "Workflow **${{ github.workflow }}** has been triggered! 🚀\r\n${GITHUB_SERVER_URL}/microsoft/LightGBM/actions/runs/${GITHUB_RUN_ID}" | ||
| - name: Build package | ||
| shell: bash | ||
| id: build_package | ||
|
|
@@ -37,3 +49,9 @@ jobs: | |
| with: | ||
| name: ${{ steps.build_package.outputs.artifact_name }} | ||
| path: ${{ steps.build_package.outputs.artifact_path }} | ||
| - name: Send final status | ||
| if: ${{ always() }} | ||
| run: | | ||
| $GITHUB_WORKSPACE/.ci/append_comment.sh \ | ||
| "${{ github.event.client_payload.comment_number }}" \ | ||
| "Status: ${{ job.status }}." | ||
|
Collaborator
Author
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. Yes, I know that direct link for artifact downloading will be more useful. But unfortunately, it is impossible:
Collaborator
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. ha it's ok, we don't use this job that often and it's only one or two more clicks to get to the artifact |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,40 @@ | ||
| name: R valgrind tests | ||
|
|
||
| on: | ||
| pull_request_review_comment: | ||
| types: [created] | ||
| repository_dispatch: | ||
| types: [gha_run_r_valgrind] | ||
|
|
||
| jobs: | ||
| test-r-valgrind: | ||
| name: r-package (ubuntu-latest, R-devel, valgrind) | ||
| if: github.event.comment.body == '/gha run r-valgrind' && contains('OWNER,MEMBER,COLLABORATOR', github.event.comment.author_association) | ||
| timeout-minutes: 120 | ||
| runs-on: ubuntu-latest | ||
| container: wch1/r-debug | ||
| env: | ||
| SECRETS_WORKFLOW: ${{ secrets.WORKFLOW }} | ||
| steps: | ||
| - name: Install essential software before checkout | ||
| shell: bash | ||
| run: | | ||
| apt-get update | ||
| apt-get install --no-install-recommends -y \ | ||
| curl \ | ||
| git \ | ||
| jq | ||
| - name: Checkout repository | ||
| uses: actions/[email protected] | ||
| with: | ||
| fetch-depth: 5 | ||
| submodules: true | ||
| repository: microsoft/LightGBM | ||
| ref: "refs/pull/${{ github.event.client_payload.pr_number }}/merge" | ||
| - name: Send init status | ||
| if: ${{ always() }} | ||
| run: | | ||
| $GITHUB_WORKSPACE/.ci/set_commit_status.sh "${{ github.workflow }}" "pending" "${{ github.event.client_payload.pr_sha }}" | ||
| $GITHUB_WORKSPACE/.ci/append_comment.sh \ | ||
| "${{ github.event.client_payload.comment_number }}" \ | ||
| "Workflow **${{ github.workflow }}** has been triggered! 🚀\r\n${GITHUB_SERVER_URL}/microsoft/LightGBM/actions/runs/${GITHUB_RUN_ID}" | ||
| - name: Install packages | ||
| shell: bash | ||
| run: | | ||
|
|
@@ -26,3 +44,18 @@ jobs: | |
| - name: Run tests with valgrind | ||
| shell: bash | ||
| run: ./.ci/test_r_package_valgrind.sh | ||
| - name: Send final status | ||
| if: ${{ always() }} | ||
| run: | | ||
| $GITHUB_WORKSPACE/.ci/set_commit_status.sh "${{ github.workflow }}" "${{ job.status }}" "${{ github.event.client_payload.pr_sha }}" | ||
| $GITHUB_WORKSPACE/.ci/append_comment.sh \ | ||
| "${{ github.event.client_payload.comment_number }}" \ | ||
| "Status: ${{ job.status }}." | ||
| - name: Rerun workflow-indicator | ||
| if: ${{ always() }} | ||
| run: | | ||
| bash $GITHUB_WORKSPACE/.ci/rerun_workflow.sh \ | ||
| "optional_checks.yml" \ | ||
| "${{ github.event.client_payload.pr_number }}" \ | ||
| "${{ github.event.client_payload.pr_branch }}" \ | ||
| || true | ||
Uh oh!
There was an error while loading. Please reload this page.