#!/usr/bin/env node const fs = require('fs') const path = require('path') const github = require('@actions/github') const enterpriseDates = require('../../lib/enterprise-dates') const { latest, oldestSupported } = require('../../lib/enterprise-server-releases') 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 = github.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() }