Unverified Commit f997a069 authored by Nikita Titov's avatar Nikita Titov Committed by GitHub
Browse files

[ci] improve experience with optional GitHub workflows (#3740)

* improve experience with optional GitHub workflows

* Update README.md

* Update r_artifacts.yml

* Update optional_checks.yml

* continue

* Update triggering_comments.yml

* Update README.md

* Update r_artifacts.yml

* Update r_artifacts.yml

* Update r_artifacts.yml

* Update r_valgrind.yml

* Update r_artifacts.yml

* Update r_valgrind.yml

* Update r_valgrind.yml

* Update r_valgrind.yml

* add docstrings to fix lint

* better formatting for multi-line commands
parent 577b2f9d
#!/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}'
)
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"
# coding: utf-8
"""Get the most recent status of workflow for the current PR."""
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
def get_runs(workflow_name):
"""Get all triggering workflow comments in the current PR.
Parameters
----------
workflow_name : string
Name of the workflow.
Returns
-------
pr_runs : list
List of comment objects sorted by the time of creation in decreasing order.
"""
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):
"""Get the most recent status of workflow for the current PR.
Parameters
----------
runs : list
List of comment objects sorted by the time of creation in decreasing order.
Returns
-------
status : string
The most recent status of workflow.
Can be 'success', 'failure' or 'in-progress'.
"""
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:
status = 'in-progress'
break
return status
if __name__ == "__main__":
workflow_name = argv[1]
while True:
status = get_status(get_runs(workflow_name))
if status != 'in-progress':
break
sleep(60)
if status == 'failure':
exit(1)
#!/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
#!/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"
#!/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"
name: Optional checks
on:
pull_request:
branches:
- master
jobs:
all-successful:
timeout-minutes: 120
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2.3.4
with:
fetch-depth: 5
submodules: false
- name: Check that all tests succeeded
run: |
workflows=("R valgrind tests")
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
name: R artifact builds name: R artifact builds
on: on:
pull_request_review_comment: repository_dispatch:
types: [created] types: [gha_run_build_r_artifacts]
jobs: jobs:
cran-package: cran-package:
name: 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 timeout-minutes: 60
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: rocker/r-base container: rocker/r-base
env:
SECRETS_WORKFLOW: ${{ secrets.WORKFLOW }}
steps: steps:
- name: Install Git before checkout - name: Install essential software before checkout
shell: bash shell: bash
run: | run: |
apt-get update apt-get update
apt-get install --no-install-recommends -y git apt-get install --no-install-recommends -y \
curl \
git \
jq
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2.3.4 uses: actions/checkout@v2.3.4
with: with:
fetch-depth: 5 fetch-depth: 5
submodules: true 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 - name: Build package
shell: bash shell: bash
id: build_package id: build_package
...@@ -37,3 +49,9 @@ jobs: ...@@ -37,3 +49,9 @@ jobs:
with: with:
name: ${{ steps.build_package.outputs.artifact_name }} name: ${{ steps.build_package.outputs.artifact_name }}
path: ${{ steps.build_package.outputs.artifact_path }} 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 }}."
name: R valgrind tests name: R valgrind tests
on: on:
pull_request_review_comment: repository_dispatch:
types: [created] types: [gha_run_r_valgrind]
jobs: jobs:
test-r-valgrind: test-r-valgrind:
name: r-package (ubuntu-latest, R-devel, 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 timeout-minutes: 120
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: wch1/r-debug container: wch1/r-debug
env:
SECRETS_WORKFLOW: ${{ secrets.WORKFLOW }}
steps: 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 - name: Checkout repository
uses: actions/checkout@v2.3.4 uses: actions/checkout@v2.3.4
with: with:
fetch-depth: 5 fetch-depth: 5
submodules: true 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 - name: Install packages
shell: bash shell: bash
run: | run: |
...@@ -26,3 +44,18 @@ jobs: ...@@ -26,3 +44,18 @@ jobs:
- name: Run tests with valgrind - name: Run tests with valgrind
shell: bash shell: bash
run: ./.ci/test_r_package_valgrind.sh 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
name: Triggering comments
on:
issue_comment:
types: [created]
jobs:
triggering-tests:
if: github.event.issue.pull_request && contains('OWNER,MEMBER,COLLABORATOR', github.event.comment.author_association)
runs-on: ubuntu-latest
env:
SECRETS_WORKFLOW: ${{ secrets.WORKFLOW }}
steps:
- name: Checkout repository
uses: actions/checkout@v2.3.4
with:
fetch-depth: 5
submodules: false
- name: Trigger R valgrind tests
if: github.event.comment.body == '/gha run r-valgrind'
run: |
$GITHUB_WORKSPACE/.ci/trigger_dispatch_run.sh \
"${{ github.event.issue.pull_request.url }}" \
"${{ github.event.comment.id }}" \
"gha_run_r_valgrind"
- name: Trigger R artifact builds
if: github.event.comment.body == '/gha run build-r-artifacts'
run: |
$GITHUB_WORKSPACE/.ci/trigger_dispatch_run.sh \
"${{ github.event.issue.pull_request.url }}" \
"${{ github.event.comment.id }}" \
"gha_run_build_r_artifacts"
...@@ -245,9 +245,9 @@ sh build-cran-package.sh ...@@ -245,9 +245,9 @@ sh build-cran-package.sh
This will create a file `lightgbm_${VERSION}.tar.gz`, where `VERSION` is the version of `LightGBM`. This will create a file `lightgbm_${VERSION}.tar.gz`, where `VERSION` is the version of `LightGBM`.
Alternatively, GitHub Actions can generate this file for you. On a pull request, go to the "Files changed" tab and create a comment with this phrase: Alternatively, GitHub Actions can generate this file for you. On a pull request, create a comment with this phrase:
> /gha build r-artifacts > /gha run build-r-artifacts
Go to https://github.com/microsoft/LightGBM/actions, and find the most recent run of the "R artifact builds" workflow. If it ran successfully, you'll find a download link for the package (in `.zip` format) in that run's "Artifacts" section. Go to https://github.com/microsoft/LightGBM/actions, and find the most recent run of the "R artifact builds" workflow. If it ran successfully, you'll find a download link for the package (in `.zip` format) in that run's "Artifacts" section.
...@@ -389,7 +389,7 @@ RDvalgrind \ ...@@ -389,7 +389,7 @@ RDvalgrind \
| cat | cat
``` ```
These tests can also be triggered on any pull request by leaving a review on the "Files changed" tab in a pull request: These tests can also be triggered on any pull request by leaving a comment in a pull request:
> /gha run r-valgrind > /gha run r-valgrind
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment