-
Notifications
You must be signed in to change notification settings - Fork 0
130 lines (117 loc) · 6.13 KB
/
manual_label_population_to_repos.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# The purpose of this workflow is to take all labels
# in this repository (neurobagel/planning) and push them
# to all repositories owned by the neurobagel organization.
#
# This workflow complements the automatic label syncing workflow
# label_sync.yml that is triggered when a label is created or edited.
# The present workflow is probably most useful when we create a new
# repository and then want to make sure that it immediately receives
# all of our standard labels.
#
# The workflow has the following jobs in this order:
# 1. get_labels: Find all labels in the planning repo and store them
# in the output variable "labels" of the job.
# 2. sync_labels: Create a separate job for each label and then within
# that job conduct the following steps:
# 2.1. read_label: Read the description and color of the label via a
# GitHub GRAPHQL API call and store them as environment variables.
# 2.2. sync_label: Find all repositories owned by neurobagel and iterate
# over them, pushing the previously stored label information to each one.
name: Manual Sync of labels
on:
workflow_dispatch
jobs:
get_labels:
name: Get all labels
runs-on: ubuntu-latest
outputs:
labels: ${{ steps.get_labels.outputs.labels }}
steps:
- id: get_labels
env:
GH_TOKEN: ${{ github.TOKEN }}
MAX_LABEL: 100
run: |
label_list=[$(gh label list -R neurobagel/planning -L ${MAX_LABEL} --json name | jq '.[].name' | jq -s -r @csv)]
echo labels: ${label_list}
echo "labels=${label_list}" >> $GITHUB_OUTPUT
sync_labels:
name: Process all the labels
runs-on: ubuntu-latest
needs: get_labels
strategy:
# Note: we cannot make a matrix for the label AND repo at once,
# because the total number of jobs will exceed the maximum allowed by GitHub.
# Therefore we create one job per label here and then iterate over the repositories
# inside of the job directly.
matrix:
label: ${{fromJSON(needs.get_labels.outputs.labels)}}
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.NB_BOT_ID }}
private-key: ${{ secrets.NB_BOT_KEY }}
# Note: We need to explicitly set the owner field here because this workflow only lives in planning but also
# makes changes in other repos.
# See https://github.com/marketplace/actions/create-github-app-token#create-a-token-for-multiple-repositories-in-the-current-owners-installation
# and https://github.com/orgs/community/discussions/69154#discussioncomment-7191057
owner: ${{ github.repository_owner }}
# To avoid setting the GH_TOKEN in every step, we set it as an environment variable
- name: Set GH_TOKEN
run: echo "GH_TOKEN=${{ steps.generate-token.outputs.token }}" >> $GITHUB_ENV
- name: read label details
id: read_label
run: |
# TODO replace hardcoded owner and repo with variables. But note that GITHUB_REPOSITORY
# in https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
# contains both owner and repo: neurobagel/planning, so we'd have to split it first
label_description="$(gh api graphql -F owner="neurobagel" -F name="planning" -F label="${{matrix.label}}" -f query='
query($owner: String!, $name: String!, $label: String!) {
repository(owner: $owner, name: $name) {
label(name: $label) {
description
}
}
}
' --jq '.data.repository.label.description')"
label_color="$(gh api graphql -F owner="neurobagel" -F name="planning" -F label="${{matrix.label}}" -f query='
query($owner: String!, $name: String!, $label: String!) {
repository(owner: $owner, name: $name) {
label(name: $label) {
color
}
}
}
' --jq '.data.repository.label.color')"
echo "description=${label_description}" >> $GITHUB_OUTPUT
echo "color=${label_color}" >> $GITHUB_OUTPUT
# Note that we have to iterate over the repositories inside of the job rather than as
# part of the job matrix because GH only allows 255 matrix jobs at a time.
# The major downside is that if any of the repositories fail, the entire step will fail
# and none of the subsequent repos will be synced.
#
# Github actions run with set -e, i.e. they immediately fail if any step has a non-zero exit status.
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
# Conveniently, grep has by default a non-zero exit status if no match is found, so we have to escape
# that the entire step to fail and all subsequent repositories to not be synced.
- name: sync label
env:
MAX_REPO: 100
run: |
for repo in $(gh repo list $GITHUB_REPOSITORY_OWNER --no-archived -L ${MAX_REPO} --json owner,name --jq '.[] | "\(.owner.login)/\(.name)"');
do
echo -e "\nSyncing label ${{matrix.label}} to ${repo}!"
# We escape grep's nonzero exit status here
out=$(gh label list -R "${repo}" -L 100 | cut -f 1 | grep -w "^${{ matrix.label }}$" || echo "")
if [ -z "${out}" ]; then
# Label missing
echo I am creating label: "${{matrix.label}}" for ${repo}
gh label create -R "${repo}" "${{matrix.label}}" --color "${{ steps.read_label.outputs.color }}" --description "${{ steps.read_label.outputs.description }}"
else
# Label exists missing
echo I am updating label: "${{matrix.label}}" for ${repo}
gh label edit -R "${repo}" "${{matrix.label}}" --color "${{ steps.read_label.outputs.color }}" --description "${{ steps.read_label.outputs.description }}"
fi
done