Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/local-actions/branch-manager/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -70237,9 +70237,16 @@ async function getJwtAuthedAppClient([appId, inputKey]) {
auth: { appId, privateKey }
});
}
async function getAuthTokenFor(app, repo2 = import_github4.context.repo) {
async function getAuthTokenFor(app, orgOrRepo = import_github4.context.repo) {
const github = await getJwtAuthedAppClient(app);
const { id } = (await github.apps.getRepoInstallation({ ...repo2 })).data;
let id;
let org = orgOrRepo;
let repo2 = orgOrRepo;
if (typeof org.org === "string") {
id = (await github.apps.getOrgInstallation({ ...org })).data.id;
} else {
id = (await github.apps.getRepoInstallation({ ...repo2 })).data.id;
}
const { token: token2 } = (await github.rest.apps.createInstallationAccessToken({
installation_id: id
})).data;
Expand Down
11 changes: 9 additions & 2 deletions .github/local-actions/changelog/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -66811,9 +66811,16 @@ async function getJwtAuthedAppClient([appId, inputKey]) {
auth: { appId, privateKey }
});
}
async function getAuthTokenFor(app, repo = import_github3.context.repo) {
async function getAuthTokenFor(app, orgOrRepo = import_github3.context.repo) {
const github = await getJwtAuthedAppClient(app);
const { id } = (await github.apps.getRepoInstallation({ ...repo })).data;
let id;
let org = orgOrRepo;
let repo = orgOrRepo;
if (typeof org.org === "string") {
id = (await github.apps.getOrgInstallation({ ...org })).data.id;
} else {
id = (await github.apps.getRepoInstallation({ ...repo })).data.id;
}
const { token } = (await github.rest.apps.createInstallationAccessToken({
installation_id: id
})).data;
Expand Down
19 changes: 0 additions & 19 deletions .github/workflows/lock-closed.yml

This file was deleted.

14 changes: 14 additions & 0 deletions .github/workflows/org-wide-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,17 @@ jobs:
angular
angular-cli
components

lock_closed:
if: github.repository == 'angular/dev-infra'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # tag=v3.3.0
- uses: ./github-actions/lock-closed
with:
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
repos: |
dev-infra
angular
angular-cli
components
11 changes: 9 additions & 2 deletions github-actions/branch-manager/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -23617,9 +23617,16 @@ async function getJwtAuthedAppClient([appId, inputKey]) {
auth: { appId, privateKey }
});
}
async function getAuthTokenFor(app, repo = import_github.context.repo) {
async function getAuthTokenFor(app, orgOrRepo = import_github.context.repo) {
const github2 = await getJwtAuthedAppClient(app);
const { id } = (await github2.apps.getRepoInstallation({ ...repo })).data;
let id;
let org = orgOrRepo;
let repo = orgOrRepo;
if (typeof org.org === "string") {
id = (await github2.apps.getOrgInstallation({ ...org })).data.id;
} else {
id = (await github2.apps.getRepoInstallation({ ...repo })).data.id;
}
const { token } = (await github2.rest.apps.createInstallationAccessToken({
installation_id: id
})).data;
Expand Down
11 changes: 9 additions & 2 deletions github-actions/commit-message-based-labels/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -32355,9 +32355,16 @@ async function getJwtAuthedAppClient([appId, inputKey]) {
auth: { appId, privateKey }
});
}
async function getAuthTokenFor(app, repo = import_github.context.repo) {
async function getAuthTokenFor(app, orgOrRepo = import_github.context.repo) {
const github = await getJwtAuthedAppClient(app);
const { id } = (await github.apps.getRepoInstallation({ ...repo })).data;
let id;
let org = orgOrRepo;
let repo = orgOrRepo;
if (typeof org.org === "string") {
id = (await github.apps.getOrgInstallation({ ...org })).data.id;
} else {
id = (await github.apps.getRepoInstallation({ ...repo })).data.id;
}
const { token } = (await github.rest.apps.createInstallationAccessToken({
installation_id: id
})).data;
Expand Down
11 changes: 9 additions & 2 deletions github-actions/feature-request/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -23499,9 +23499,16 @@ async function getJwtAuthedAppClient([appId, inputKey]) {
auth: { appId, privateKey }
});
}
async function getAuthTokenFor(app, repo = import_github.context.repo) {
async function getAuthTokenFor(app, orgOrRepo = import_github.context.repo) {
const github = await getJwtAuthedAppClient(app);
const { id } = (await github.apps.getRepoInstallation({ ...repo })).data;
let id;
let org = orgOrRepo;
let repo = orgOrRepo;
if (typeof org.org === "string") {
id = (await github.apps.getOrgInstallation({ ...org })).data.id;
} else {
id = (await github.apps.getRepoInstallation({ ...repo })).data.id;
}
const { token } = (await github.rest.apps.createInstallationAccessToken({
installation_id: id
})).data;
Expand Down
11 changes: 9 additions & 2 deletions github-actions/labels-sync/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -23617,9 +23617,16 @@ async function getJwtAuthedAppClient([appId, inputKey]) {
auth: { appId, privateKey }
});
}
async function getAuthTokenFor(app, repo = import_github.context.repo) {
async function getAuthTokenFor(app, orgOrRepo = import_github.context.repo) {
const github = await getJwtAuthedAppClient(app);
const { id } = (await github.apps.getRepoInstallation({ ...repo })).data;
let id;
let org = orgOrRepo;
let repo = orgOrRepo;
if (typeof org.org === "string") {
id = (await github.apps.getOrgInstallation({ ...org })).data.id;
} else {
id = (await github.apps.getRepoInstallation({ ...repo })).data.id;
}
const { token } = (await github.rest.apps.createInstallationAccessToken({
installation_id: id
})).data;
Expand Down
54 changes: 30 additions & 24 deletions github-actions/lock-closed/lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ import {context} from '@actions/github';
import {Octokit} from '@octokit/rest';
import {ANGULAR_LOCK_BOT, getAuthTokenFor, revokeActiveInstallationToken} from '../../utils.js';

async function lockIssue(client: Octokit, issue: number, message: string): Promise<void> {
async function lockIssue(
client: Octokit,
issue: number,
repo: string,
message: string,
): Promise<void> {
await client.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
repo,
owner: 'angular',
issue_number: issue,
body: message,
});

// Actually lock the issue
await client.issues.lock({
owner: context.repo.owner,
repo: context.repo.repo,
repo,
owner: 'angular',
issue_number: issue,
});
}
Expand All @@ -25,13 +30,17 @@ function timeout(ms: number) {
}

async function main() {
let installationClient: Octokit | null = null;
const reposToBeChecked = core.getMultilineInput('repos', {required: true, trimWhitespace: true});
await core.group('Repos being checked for lockable issues:', async () =>
reposToBeChecked.forEach((repo) => core.info(`- ${repo}`)),
);
const token = await getAuthTokenFor(ANGULAR_LOCK_BOT, {org: 'angular'});

try {
const token = await getAuthTokenFor(ANGULAR_LOCK_BOT);
installationClient = new Octokit({auth: token});

await runLockClosedAction(installationClient);
const github = new Octokit({auth: token});
for (let repo of reposToBeChecked) {
await runLockClosedAction(github, repo);
}
} catch (error: any) {
// TODO(josephperrott): properly set typings for error.
core.debug(error.message);
Expand All @@ -40,13 +49,11 @@ async function main() {
core.error(JSON.stringify(error.request, null, 2));
}
} finally {
if (installationClient !== null) {
await revokeActiveInstallationToken(installationClient);
}
await revokeActiveInstallationToken(token);
}
}

async function runLockClosedAction(github: Octokit): Promise<void> {
async function runLockClosedAction(github: Octokit, repo: string): Promise<void> {
// NOTE: `days` and `message` must not be changed without dev-rel and dev-infra concurrence

// Fixed amount of days a closed issue must be inactive before being locked
Expand All @@ -60,20 +67,20 @@ async function runLockClosedAction(github: Octokit): Promise<void> {
`Read more about our [automatic conversation locking policy](${policyUrl}).\n\n` +
'<sub>_This action has been performed automatically by a bot._</sub>';

const maxPerExecution = Math.min(+core.getInput('locks-per-execution') || 1, 100);
// Set the threshold date based on the days inactive
const threshold = new Date();
threshold.setDate(threshold.getDate() - days);

const repositoryName = context.repo.owner + '/' + context.repo.repo;
const repositoryName = `angular/${repo}`;
const updatedAt = threshold.toISOString().split('T')[0];
const query = `repo:${repositoryName}+is:closed+is:unlocked+updated:<${updatedAt}+sort:updated-asc`;
console.info('Query: ' + query);

let lockCount = 0;
let issueResponse = await github.search.issuesAndPullRequests({
q: query,
per_page: maxPerExecution,
// We process 100 issues/prs per run, which will catch up over time as necessary.
per_page: 100,
});

console.info(`Query found ${issueResponse.data.total_count} items`);
Expand All @@ -86,21 +93,20 @@ async function runLockClosedAction(github: Octokit): Promise<void> {
console.info(`Attempting to lock ${issueResponse.data.items.length} item(s)`);
core.startGroup('Locking items');
for (const item of issueResponse.data.items) {
let itemType: string | undefined;
const itemType = item.pull_request ? 'pull request' : 'issue';
try {
itemType = item.pull_request ? 'pull request' : 'issue';
if ((item as any).locked) {
console.info(`Skipping ${itemType} #${item.number}, already locked`);
if (item.locked) {
console.info(`Skipping ${itemType} angular/${repo}#${item.number}, already locked`);
continue;
}
console.info(`Locking ${itemType} #${item.number}`);
await lockIssue(github, item.number, message);
await timeout(500);
await lockIssue(github, item.number, repo, message);
await timeout(250);
++lockCount;
} catch (error: any) {
// TODO(josephperrott): properly set typings for error.
core.debug(error);
core.warning(`Unable to lock ${itemType} #${item.number}: ${error.message}`);
core.warning(`Unable to lock ${itemType} angular/${repo}#${item.number}: ${error.message}`);
if (typeof error.request === 'object') {
core.error(JSON.stringify(error.request, null, 2));
}
Expand Down
Loading