forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate-enterprise-issue.js
More file actions
executable file
·160 lines (138 loc) · 5.37 KB
/
create-enterprise-issue.js
File metadata and controls
executable file
·160 lines (138 loc) · 5.37 KB
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
#!/usr/bin/env node
import fs from 'fs'
import path from 'path'
import { getOctokit } from '@actions/github'
import enterpriseDates from '../../lib/enterprise-dates.js'
import { latest, oldestSupported } from '../../lib/enterprise-server-releases.js'
const acceptedMilestones = ['release', 'deprecation']
const teamsToCC = '/cc @github/docs-content @github/docs-engineering'
// Adjust these values as needed.
const numberOfdaysBeforeReleaseToOpenIssue = 30
const numberOfdaysBeforeDeprecationToOpenIssue = 15
// [start-readme]
//
// This script runs once per day via a scheduled GitHub Action to check whether
// an Enterprise release or deprecation milestone is within the specified
// number of days.
//
// When a milestone is within the specified number of days, a new issue is
// created using the templates in
// .github/actions-scripts/enterprise-server-issue-templates.
//
// Release issues are then added to the docs content squad board for triage.
// Deprecations issues are owned by docs engineering and are added to the
// docs engineering squad board automatically when the engineering label is added.
//
// [end-readme]
run()
async function run() {
const milestone = process.argv[2]
if (!acceptedMilestones.includes(milestone)) {
console.log("Please specify either 'release' or 'deprecation'\n")
console.log('Example: script/open-enterprise-issue.js release')
process.exit(1)
}
// Milestone-dependent values.
const numberOfdaysBeforeMilestoneToOpenIssue =
milestone === 'release'
? numberOfdaysBeforeReleaseToOpenIssue
: numberOfdaysBeforeDeprecationToOpenIssue
const versionNumber = milestone === 'release' ? getNextVersionNumber() : oldestSupported
if (!versionNumber) {
console.log(
`Could not find the next version number after ${latest} in enterprise-dates.json. Try running script/udpate-enterprise-dates.js, then rerun this script.`
)
process.exit(0)
}
const datesForVersion = enterpriseDates[versionNumber]
if (!datesForVersion) {
console.log(
`Could not find ${versionNumber} in enterprise-dates.json. Try running script/udpate-enterprise-dates.js, then rerun this script.`
)
process.exit(0)
}
const nextMilestoneDate = datesForVersion[`${milestone}Date`]
const daysUntilMilestone = calculateDaysUntilMilestone(nextMilestoneDate)
// If the milestone is more than the specific days away, exit now.
if (daysUntilMilestone > numberOfdaysBeforeMilestoneToOpenIssue) {
console.log(
`The ${versionNumber} ${milestone} is not until ${nextMilestoneDate}! An issue will be opened when it is ${numberOfdaysBeforeMilestoneToOpenIssue} days away.`
)
process.exit(0)
}
const milestoneSteps = fs.readFileSync(
path.join(
process.cwd(),
`.github/actions-scripts/enterprise-server-issue-templates/${milestone}-issue.md`
),
'utf8'
)
const issueLabels = [`enterprise ${milestone}`, `engineering`]
const issueTitle = `[${nextMilestoneDate}] Enterprise Server ${versionNumber} ${milestone} (technical steps)`
const issueBody = `GHES ${versionNumber} ${milestone} occurs on ${nextMilestoneDate}.
\n${milestoneSteps}
${teamsToCC}`
const token = process.env.GITHUB_TOKEN
// Create the milestone issue
const octokit = getOctokit(token)
try {
issue = await octokit.request('POST /repos/{owner}/{repo}/issues', {
owner: 'github',
repo: 'docs-internal',
title: issueTitle,
body: issueBody,
labels: issueLabels,
})
if (issue.status === 201) {
// Write the values to disk for use in the workflow.
console.log(
`Issue #${issue.data.number} for the ${versionNumber} ${milestone} was opened: ${issue.data.html_url}`
)
}
} catch (error) {
console.error(`#ERROR# ${error}`)
console.log(`🛑 There was an error creating the issue.`)
process.exit(1)
}
// Add the release issue to the 'Needs triage' column on the
// docs content squad project board:
// https://github.com/orgs/github/projects/1773#column-12198119
// Deprecation issues are owned by docs engineering only and will
// be triaged by adding the engineering label to the issue.
if (milestone === 'release') {
try {
const addCard = await octokit.request('POST /projects/columns/{column_id}/cards', {
column_id: 12198119,
content_id: issue.data.id,
content_type: 'Issue',
mediaType: {
previews: ['inertia'],
},
})
if (addCard.status === 201) {
// Write the values to disk for use in the workflow.
console.log(
`The issue #${issue.data.number} was added to https://github.com/orgs/github/projects/1773#column-12198119.`
)
}
} catch (error) {
console.error(`#ERROR# ${error}`)
console.log(`🛑 There was an error adding the issue to the project board.`)
process.exit(1)
}
}
}
function getNextVersionNumber() {
const indexOfLatest = Object.keys(enterpriseDates).indexOf(latest)
const indexOfNext = indexOfLatest + 1
return Object.keys(enterpriseDates)[indexOfNext]
}
function calculateDaysUntilMilestone(nextMilestoneDate) {
const today = new Date().toISOString().slice(0, 10)
const differenceInMilliseconds = getTime(nextMilestoneDate) - getTime(today)
// Return the difference in days
return Math.floor(differenceInMilliseconds / (1000 * 60 * 60 * 24))
}
function getTime(date) {
return new Date(date).getTime()
}