-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ci: notify with GH issue + project item on e2e failure (#2607)
Signed-off-by: Paul Meyer <[email protected]> Co-authored-by: Paul Meyer <[email protected]>
- Loading branch information
1 parent
284c7e9
commit ed22137
Showing
3 changed files
with
358 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
name: Create a GitHub issue | ||
description: "Create an issue on GitHub, and optionally add it to a project board." | ||
|
||
inputs: | ||
title: | ||
description: "The title of the issue." | ||
required: true | ||
owner: | ||
description: "The owner of the repository to create the issue in." | ||
required: false | ||
default: ${{ github.repository_owner }} | ||
repo: | ||
description: "The repository to create the issue in." | ||
required: false | ||
default: ${{ github.repository }} | ||
token: | ||
description: "The GitHub token to use to authenticate." | ||
required: false | ||
default: ${{ github.token }} | ||
body: | ||
description: "The body of the issue." | ||
required: false | ||
body-file: | ||
description: "The absolute path to a file containing the body of the issue." | ||
required: false | ||
assignee: | ||
description: "The GitHub username to assign the issue to." | ||
required: false | ||
label: | ||
description: "A comma-separated list of labels to add to the issue." | ||
required: false | ||
milestone: | ||
description: "The milestone to add the issue to." | ||
required: false | ||
project: | ||
description: "Number of the project to add the issue to." | ||
required: false | ||
template: | ||
description: "The template to use for the issue." | ||
required: false | ||
fields: | ||
description: "A JSON object containing the fields to use for the issue." | ||
required: false | ||
|
||
outputs: | ||
issue-url: | ||
description: "The URL of the created issue." | ||
value: ${{ steps.run.outputs.issue-url }} | ||
|
||
runs: | ||
using: "composite" | ||
steps: | ||
- name: Run create_issue.sh | ||
id: run | ||
shell: bash | ||
env: | ||
GH_TOKEN: ${{ inputs.token }} | ||
run: | | ||
set -x | ||
cat << EOF | tee inputs.json | ||
${{ toJSON(inputs) }} | ||
EOF | ||
out=$(./.github/actions/gh_create_issue/create_issue.sh inputs.json) | ||
echo "issue-url=${out}" | tee -a "$GITHUB_OUTPUT" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -euo pipefail | ||
|
||
function debug() { | ||
echo "DEBUG: $*" >&2 | ||
} | ||
|
||
function warn() { | ||
echo "WARN: $*" >&2 | ||
} | ||
|
||
function inputs() { | ||
name="${1}" | ||
local val | ||
val=$(jq -r ".\"${name}\"" "${inputFile}") | ||
if [[ ${val} == "null" ]]; then | ||
warn "Input ${name} not found in ${inputFile}" | ||
return | ||
fi | ||
echo "${val}" | ||
} | ||
|
||
function flagsFromInput() { | ||
flagNames=("${@}") | ||
for name in "${flagNames[@]}"; do | ||
val=$(inputs "${name}") | ||
if [[ -n ${val} ]]; then | ||
echo "--${name}=${val}" | ||
fi | ||
done | ||
} | ||
|
||
function createIssue() { | ||
flags=( | ||
"assignee" | ||
"body" | ||
"body-file" | ||
"label" | ||
"milestone" | ||
"project" | ||
"template" | ||
"title" | ||
) | ||
readarray -t flags <<< "$(flagsFromInput "${flags[@]}")" | ||
flags+=("--repo=$(inputs owner)/$(inputs repo)") | ||
debug gh issue create "${flags[@]}" | ||
gh issue create "${flags[@]}" | ||
} | ||
|
||
function listProjects() { | ||
flags=( | ||
"owner" | ||
) | ||
readarray -t flags <<< "$(flagsFromInput "${flags[@]}")" | ||
flags+=("--format=json") | ||
debug gh project list "${flags[@]}" | ||
gh project list "${flags[@]}" >> projects.json | ||
} | ||
|
||
function findProjectID() { | ||
project=$(inputs "project") | ||
out="$( | ||
jq -r \ | ||
--arg project "${project}" \ | ||
'.projects[] | ||
| select(.title == $project) | ||
| .id' \ | ||
projects.json | ||
)" | ||
debug "Project ID: ${out}" | ||
echo "${out}" | ||
} | ||
|
||
function findProjectNo() { | ||
project=$(inputs "project") | ||
out="$( | ||
jq -r \ | ||
--arg project "${project}" \ | ||
'.projects[] | ||
| select(.title == $project) | ||
| .number' \ | ||
projects.json | ||
)" | ||
debug "Project Number: ${out}" | ||
echo "${out}" | ||
} | ||
|
||
function listItems() { | ||
local projectNo="${1}" | ||
flags=( | ||
"owner" | ||
) | ||
readarray -t flags <<< "$(flagsFromInput "${flags[@]}")" | ||
flags+=("--limit=1000") | ||
flags+=("--format=json") | ||
debug gh project item-list "${flags[@]}" "${projectNo}" | ||
gh project item-list "${flags[@]}" "${projectNo}" >> issues.json | ||
} | ||
|
||
function findIssueItemID() { | ||
local issueURL="${1}" | ||
out="$( | ||
jq -r \ | ||
--arg issueURL "${issueURL}" \ | ||
'.items[] | ||
| select(.content.url == $issueURL) | ||
| .id' \ | ||
issues.json | ||
)" | ||
debug "Issue Item ID: ${out}" | ||
echo "${out}" | ||
} | ||
|
||
function listFields() { | ||
local projectNo="${1}" | ||
flags=( | ||
"owner" | ||
) | ||
readarray -t flags <<< "$(flagsFromInput "${flags[@]}")" | ||
flags+=("--limit=1000") | ||
flags+=("--format=json") | ||
debug gh project field-list "${flags[@]}" "${projectNo}" | ||
gh project field-list "${flags[@]}" "${projectNo}" >> fields.json | ||
} | ||
|
||
function findFieldID() { | ||
local fieldName="${1}" | ||
out="$( | ||
jq -r \ | ||
--arg fieldName "${fieldName}" \ | ||
'.fields[] | ||
| select(.name == $fieldName) | ||
| .id' \ | ||
fields.json | ||
)" | ||
debug "Field ID of '${fieldName}': ${out}" | ||
echo "${out}" | ||
} | ||
|
||
function findSelectFieldID() { | ||
local fieldName="${1}" | ||
local fieldValue="${2}" | ||
out="$( | ||
jq -r \ | ||
--arg fieldName "${fieldName}" \ | ||
--arg fieldValue "${fieldValue}" \ | ||
'.fields[] | ||
| select(.name == $fieldName) | ||
| .options[] | ||
| select(.name == $fieldValue) | ||
| .id' \ | ||
fields.json | ||
)" | ||
debug "Field ID of '${fieldName}': ${out}" | ||
echo "${out}" | ||
} | ||
|
||
function findFieldType() { | ||
local fieldName="${1}" | ||
out="$( | ||
jq -r \ | ||
--arg fieldName "${fieldName}" \ | ||
'.fields[] | ||
| select(.name == $fieldName) | ||
| .type' \ | ||
fields.json | ||
)" | ||
debug "Field type of '${fieldName}': ${out}" | ||
echo "${out}" | ||
} | ||
|
||
function editItem() { | ||
local projectID="${1}" | ||
local itemID="${2}" | ||
local id="${3}" | ||
local value="${4}" | ||
flags=( | ||
"--project-id=${projectID}" | ||
"--id=${itemID}" | ||
"--field-id=${id}" | ||
"--text=${value}" | ||
) | ||
debug gh project item-edit "${flags[@]}" | ||
gh project item-edit "${flags[@]}" > /dev/null | ||
} | ||
|
||
function setFields() { | ||
local projectID="${1}" | ||
local itemID="${2}" | ||
|
||
fieldsLen="$(jq -r '.fields' "${inputFile}" | yq 'length')" | ||
debug "Number of fields in input: ${fieldsLen}" | ||
for ((i = 0; i < fieldsLen; i++)); do | ||
name="$(jq -r '.fields' "${inputFile}" | | ||
yq "to_entries | .[${i}].key")" | ||
value="$(jq -r '.fields' "${inputFile}" | | ||
yq "to_entries | .[${i}].value")" | ||
debug "Field ${i}: ${name} = ${value}" | ||
type=$(findFieldType "${name}") | ||
|
||
case "${type}" in | ||
"ProjectV2Field") | ||
id=$(findFieldID "${name}") | ||
;; | ||
"ProjectV2SingleSelectField") | ||
id=$(findSelectFieldID "${name}" "${value}") | ||
;; | ||
*) | ||
warn "Unknown field type: ${type}" | ||
return 1 | ||
;; | ||
esac | ||
|
||
editItem "${projectID}" "${itemID}" "${id}" "${value}" | ||
done | ||
} | ||
|
||
function main() { | ||
inputFile="$(realpath "${1}")" | ||
|
||
workdir=$(mktemp -d) | ||
pushd "${workdir}" > /dev/null | ||
trap 'debug "not cleaning up, working directory at: ${workdir}"' ERR | ||
|
||
issueURL=$(createIssue) | ||
echo "${issueURL}" | ||
|
||
project=$(inputs "project") | ||
if [[ -z ${project} ]]; then | ||
return | ||
fi | ||
|
||
listProjects | ||
projectNo=$(findProjectNo) | ||
projectID=$(findProjectID) | ||
|
||
listItems "${projectNo}" | ||
issueItemID=$(findIssueItemID "${issueURL}") | ||
listFields "${projectNo}" | ||
|
||
setFields "${projectID}" "${issueItemID}" | ||
|
||
popd > /dev/null | ||
rm -rf "${workdir}" | ||
} | ||
|
||
main "${@}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters