-
Notifications
You must be signed in to change notification settings - Fork 5
200 lines (188 loc) · 9.33 KB
/
_reusable_add-content-to-project.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# This is a reusable workflow; see https://docs.github.com/en/actions/using-workflows/reusing-workflows.
# It was created because GitHub projects' workflows (see e.g. https://github.com/orgs/MAKENTNU/projects/1/workflows)
# don't (currently) support doing the specific things done in the steps below.
#
# The workflow requires that the following repository variables have been created:
# - `ORGANIZATION_PROJECT_NUMBER` - The number/ID in the project URL (https://github.com/orgs/MAKENTNU/projects/1)
# - `ORGANIZATION_PROJECT__DATE_FIELD_NAME` - The name of the project's date field
# - `ORGANIZATION_PROJECT__STATUS_VALUE_FOR_CLOSED_ITEMS` - The value of the 'Status' field set for an item when closed
# (see https://github.com/orgs/MAKENTNU/projects/1/workflows/3569450)
# and the following organization variables:
# - `ORGANIZATION_NAME` - The name of the organization in the project URL (https://github.com/orgs/MAKENTNU/projects/1)
#
# The workflow also expects that the following project workflows are turned on for the project:
# - "Item closed" (https://github.com/orgs/MAKENTNU/projects/1/workflows/3569450):
# - "When an item is closed": "issue, pull request"
# - "Set value": "Status: <the value of the `ORGANIZATION_PROJECT__STATUS_VALUE_FOR_CLOSED_ITEMS` repository variable>"
# and that the following project workflows are turned off:
# - "Item added to project"
# - "Item reopened"
# (The "Pull request merged" project workflow (https://github.com/orgs/MAKENTNU/projects/1/workflows/3569451)
# does not affect and is not affected by any of this.
# However, it could be natural that it sets the same value as the "Item closed" project workflow.)
name: Add content to project
on:
workflow_call:
inputs:
content_id:
description: "The ID of an issue or a PR, to be added to this repo's GitHub project"
required: true
type: string
status_field_value_name:
description: "The name of one of the values of the project's (single select) 'Status' field, to set for the added project item"
required: true
type: string
jobs:
add_content:
runs-on: ubuntu-latest
# Code based on https://docs.github.com/en/issues/planning-and-tracking-with-projects/automating-your-project/automating-projects-using-actions#example-workflow-authenticating-with-a-github-app
steps:
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0
with:
app_id: ${{ secrets.MAKE_BOT_APP_ID }}
private_key: ${{ secrets.MAKE_BOT_APP_PEM }}
- name: Get project data
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
ORGANIZATION: ${{ vars.ORGANIZATION_NAME }}
PROJECT_NUMBER: ${{ vars.ORGANIZATION_PROJECT_NUMBER }}
DATE_FIELD_NAME: ${{ vars.ORGANIZATION_PROJECT__DATE_FIELD_NAME }}
# This name is hardcoded by GitHub and cannot be changed
STATUS_FIELD_NAME: Status
STATUS_FIELD_VALUE_NAME: ${{ inputs.status_field_value_name }}
run: |
gh api graphql -f query='
query ($org: String!, $number: Int!) {
organization(login: $org) {
projectV2(number: $number) {
id
fields(first: 20) {
nodes {
... on ProjectV2Field {
id
name
}
... on ProjectV2SingleSelectField {
id
name
options {
id
name
}
}
}
}
}
}
}' -f org="$ORGANIZATION" -F number="$PROJECT_NUMBER" > project_data.json
{
# The ID of this repo's GitHub project
echo "PROJECT_ID=$(jq -r '.data.organization.projectV2.id' project_data.json)"
# The ID of the project's date field
echo "DATE_FIELD_ID=$(jq --arg FIELD_NAME "$DATE_FIELD_NAME" -r '.data.organization.projectV2.fields.nodes[] | select(.name==$FIELD_NAME) | .id' project_data.json)"
# The ID of the project's status field
echo "STATUS_FIELD_ID=$(jq --arg FIELD_NAME "$STATUS_FIELD_NAME" -r '.data.organization.projectV2.fields.nodes[] | select(.name==$FIELD_NAME) | .id' project_data.json)"
# The ID of one of the values of the project's (single select) status field, with name `inputs.status_field_value_name`
echo "STATUS_FIELD_VALUE_ID=$(jq --arg FIELD_NAME "$STATUS_FIELD_NAME" --arg STATUS_NAME "$STATUS_FIELD_VALUE_NAME" -r '.data.organization.projectV2.fields.nodes[] | select(.name==$FIELD_NAME) | .options[] | select(.name==$STATUS_NAME) | .id' project_data.json)"
} >> "$GITHUB_ENV"
- name: Add content to project
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
CONTENT_ID: ${{ inputs.content_id }}
run: |
item_id="$( gh api graphql -f query='
mutation ($project: ID!, $content: ID!) {
addProjectV2ItemById(input: {projectId: $project, contentId: $content}) {
item {
id
}
}
}' -f project="$PROJECT_ID" -f content="$CONTENT_ID" --jq '.data.addProjectV2ItemById.item.id' )"
# The ID of the project item (representing an issue or a PR with ID `inputs.content_id`), which was either added or already existed
echo "ITEM_ID=$item_id" >> "$GITHUB_ENV"
- name: Get project item data
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
gh api graphql -f query='
query ($itemId: ID!) {
node(id: $itemId) {
... on ProjectV2Item {
fieldValues(first: 20) {
nodes {
... on ProjectV2ItemFieldSingleSelectValue {
name
field {
... on ProjectV2SingleSelectField {
id
}
}
}
... on ProjectV2ItemFieldDateValue {
date
field {
... on ProjectV2Field {
id
}
}
}
}
}
}
}
}' -f itemId="$ITEM_ID" > project_item_data.json
{
# The value of the project item's date field (with ID `env.DATE_FIELD_ID`)
echo "DATE_FIELD_VALUE=$(jq --arg FIELD_ID "$DATE_FIELD_ID" -r '.data.node.fieldValues.nodes[] | select(.field.id==$FIELD_ID) | .date' project_item_data.json)"
# The value of the project item's status field (with ID `env.STATUS_FIELD_ID`)
echo "STATUS_FIELD_VALUE=$(jq --arg FIELD_ID "$STATUS_FIELD_ID" -r '.data.node.fieldValues.nodes[] | select(.field.id==$FIELD_ID) | .name' project_item_data.json)"
} >> "$GITHUB_ENV"
- name: Set status
# Only set the status if it's not already set,
# or if it's a reopened issue/PR (as they should be marked with the value of `ORGANIZATION_PROJECT__STATUS_VALUE_FOR_CLOSED_ITEMS` when closed
# - see https://github.com/orgs/MAKENTNU/projects/1/workflows/3569450)
if: ${{ !env.STATUS_FIELD_VALUE
|| github.event.action == 'reopened' && env.STATUS_FIELD_VALUE == vars.ORGANIZATION_PROJECT__STATUS_VALUE_FOR_CLOSED_ITEMS }}
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
gh api graphql -f query='
mutation ($project: ID!, $item: ID!, $status_field: ID!, $status_value: String!) {
set_status: updateProjectV2ItemFieldValue(input: {
projectId: $project
itemId: $item
fieldId: $status_field
value: {
singleSelectOptionId: $status_value
}
}) {
projectV2Item {
id
}
}
}' -f project="$PROJECT_ID" -f item="$ITEM_ID" -f status_field="$STATUS_FIELD_ID" -f status_value="$STATUS_FIELD_VALUE_ID" --silent
- name: Get date
run: echo "DATE=$(TZ='Europe/Oslo' date --iso-8601)" >> "$GITHUB_ENV"
- name: Set date
# Only set the date if it's not already set
if: ${{ !env.DATE_FIELD_VALUE }}
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
gh api graphql -f query='
mutation ($project: ID!, $item: ID!, $date_field: ID!, $date_value: Date!) {
set_date_posted: updateProjectV2ItemFieldValue(input: {
projectId: $project
itemId: $item
fieldId: $date_field
value: {
date: $date_value
}
}) {
projectV2Item {
id
}
}
}' -f project="$PROJECT_ID" -f item="$ITEM_ID" -f date_field="$DATE_FIELD_ID" -f date_value="$DATE" --silent