Skip to content

Commit

Permalink
[ci] improve experience with optional GitHub workflows (#3740)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
StrikerRUS authored Jan 13, 2021
1 parent 577b2f9 commit f997a06
Show file tree
Hide file tree
Showing 10 changed files with 404 additions and 11 deletions.
50 changes: 50 additions & 0 deletions .ci/append_comment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/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"
82 changes: 82 additions & 0 deletions .ci/get_workflow_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# 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)
47 changes: 47 additions & 0 deletions .ci/rerun_workflow.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/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
53 changes: 53 additions & 0 deletions .ci/set_commit_status.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/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"
51 changes: 51 additions & 0 deletions .ci/trigger_dispatch_run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/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"
25 changes: 25 additions & 0 deletions .github/workflows/optional_checks.yml
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/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
28 changes: 23 additions & 5 deletions .github/workflows/r_artifacts.yml
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/checkout@v2.3.4
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
Expand All @@ -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 }}."
Loading

0 comments on commit f997a06

Please sign in to comment.