-
Notifications
You must be signed in to change notification settings - Fork 21
chore(ci): authenticate release issue by approval comment #316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
fb6392c
21ce8c0
fd73907
436b77e
1c66be4
097026e
3239ac8
6794008
4a8971e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
import fsp from 'fs/promises'; | ||
import path from 'path'; | ||
|
||
import { Octokit } from '@octokit/rest'; | ||
import dotenv from 'dotenv'; | ||
import execa from 'execa'; | ||
import { copy, remove } from 'fs-extra'; | ||
|
@@ -23,6 +24,7 @@ import { | |
RELEASED_TAG, | ||
OWNER, | ||
REPO, | ||
TEAM_SLUG, | ||
getMarkdownSection, | ||
configureGitHubAuthor, | ||
cloneRepository, | ||
|
@@ -32,6 +34,10 @@ import type { VersionsToRelease } from './types'; | |
|
||
dotenv.config({ path: ROOT_ENV_PATH }); | ||
|
||
const octokit = new Octokit({ | ||
auth: `token ${process.env.GITHUB_TOKEN}`, | ||
}); | ||
|
||
type BeforeClientGenerationCommand = (params: { | ||
releaseType: ReleaseType; | ||
dir: string; | ||
|
@@ -45,14 +51,16 @@ const BEFORE_CLIENT_GENERATION: { | |
}, | ||
}; | ||
|
||
function getIssueBody(): string { | ||
return JSON.parse( | ||
execa.sync('curl', [ | ||
'-H', | ||
`Authorization: token ${process.env.GITHUB_TOKEN}`, | ||
`https://api.github.com/repos/${OWNER}/${REPO}/issues/${process.env.EVENT_NUMBER}`, | ||
]).stdout | ||
).body; | ||
async function getIssueBody(): Promise<string> { | ||
const { | ||
data: { body }, | ||
} = await octokit.rest.issues.get({ | ||
owner: OWNER, | ||
repo: REPO, | ||
issue_number: Number(process.env.EVENT_NUMBER), | ||
}); | ||
|
||
return body ?? ''; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we fail if we can't find the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know why octokit provides such type definition, but according to their rest api docs, it doesn't mention anything about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes but it's better to bail early rather that doing a bunch of work that could fail later and don't know where the error is coming from, unless it's all silent in the end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah it makes sense 097026e |
||
} | ||
|
||
function getDateStamp(): string { | ||
|
@@ -149,6 +157,25 @@ async function updateChangelog({ | |
); | ||
} | ||
|
||
async function isAuthorizedRelease(): Promise<boolean> { | ||
const { data: members } = await octokit.rest.teams.listMembersInOrg({ | ||
org: OWNER, | ||
team_slug: TEAM_SLUG, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although I get the idea, I wonder if it's good to check if it's a team member. The end goal of this project is to let anyone from the company contribute to our clients, which would not match this condition. Wdyt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's still okay. Anyone can open pull-requests and contribute to the code base, but only us can trigger releases. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe anyone at algolia should be able to release ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would still be the bottleneck, IMO anyone from the company should have the rights to do it, we are just here to make sure it works well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't we start with a small scope and expand later if there's a demand and if we think it makes sense to allow them to trigger releases? Anyway we can replace this small piece of code quite easily if we want. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep I think it's fair at the moment to start with only us. We want anyone to contribute but it's very unlikely that we want unattended release There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I was mostly pointing it out but let's not forget about this |
||
}); | ||
|
||
const { data: comments } = await octokit.rest.issues.listComments({ | ||
owner: OWNER, | ||
repo: REPO, | ||
issue_number: Number(process.env.EVENT_NUMBER), | ||
}); | ||
|
||
return comments.some( | ||
(comment) => | ||
comment.body?.toLowerCase().includes('approved') && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah it should be more stricter. 1c66be4 |
||
members.find((member) => member.login === comment.user?.login) | ||
); | ||
} | ||
|
||
async function processRelease(): Promise<void> { | ||
if (!process.env.GITHUB_TOKEN) { | ||
throw new Error('Environment variable `GITHUB_TOKEN` does not exist.'); | ||
|
@@ -158,16 +185,13 @@ async function processRelease(): Promise<void> { | |
throw new Error('Environment variable `EVENT_NUMBER` does not exist.'); | ||
} | ||
|
||
const issueBody = getIssueBody(); | ||
|
||
if ( | ||
!getMarkdownSection(issueBody, TEXT.approvalHeader) | ||
.split('\n') | ||
.find((line) => line.startsWith(`- [x] ${TEXT.approved}`)) | ||
) { | ||
throw new Error('The issue was not approved.'); | ||
if (!(await isAuthorizedRelease())) { | ||
throw new Error( | ||
'The issue was not approved.\nA team member must leave a comment "approved" in the release issue.' | ||
); | ||
} | ||
|
||
const issueBody = await getIssueBody(); | ||
const versionsToRelease = getVersionsToRelease(issueBody); | ||
|
||
await updateOpenApiTools(versionsToRelease); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be in some common file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced on this. If we were to abstract all the octokit-related functions, then it'd make sense. But having only this part abstracted in a common file, I don't see much value. Besides, we have only two occurrences of
new Octokit()
across the code base. We could do it when there's a third time ;)https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I count 3 ahah
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahhhh you win. I somehow saw only two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💪
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3239ac8