Add state

This commit is contained in:
Sergey Dolin
2023-06-22 13:20:34 +02:00
parent 51c18470e1
commit 79fe616082
24 changed files with 7306 additions and 44 deletions

View File

@@ -17,6 +17,8 @@ export class ExemptDraftPullRequest {
}
async shouldExemptDraftPullRequest(
// keep this for backward compatibility
// eslint-disable-next-line @typescript-eslint/no-unused-vars
pullRequestCallback: () => Promise<IPullRequest | undefined | void>
): Promise<boolean> {
if (this._issue.isPullRequest) {

View File

@@ -71,6 +71,7 @@ describe('Issue', (): void => {
number: 8,
created_at: 'dummy-created-at',
updated_at: 'dummy-updated-at',
draft: false,
labels: [
{
name: 'dummy-name'

View File

@@ -34,7 +34,7 @@ export class Issue implements IIssue {
this.number = issue.number;
this.created_at = issue.created_at;
this.updated_at = issue.updated_at;
this.draft = issue.draft || false;
this.draft = Boolean(issue.draft);
this.labels = mapLabels(issue.labels);
this.pull_request = issue.pull_request;
this.state = issue.state;

View File

@@ -26,6 +26,7 @@ import {Statistics} from './statistics';
import {LoggerService} from '../services/logger.service';
import {OctokitIssue} from '../interfaces/issue';
import {retry} from '@octokit/plugin-retry';
import {IState} from '../interfaces/state';
/***
* Handle processing of issues for staleness/closure.
@@ -72,9 +73,11 @@ export class IssuesProcessor {
readonly addedCloseCommentIssues: Issue[] = [];
readonly statistics: Statistics | undefined;
private readonly _logger: Logger = new Logger();
private readonly state: IState;
constructor(options: IIssuesProcessorOptions) {
constructor(options: IIssuesProcessorOptions, state: IState) {
this.options = options;
this.state = state;
this.client = getOctokit(this.options.repoToken, undefined, retry);
this.operations = new StaleOperations(this.options);
@@ -110,6 +113,8 @@ export class IssuesProcessor {
?.setOperationsCount(this.operations.getConsumedOperationsCount())
.logStats();
this.state.reset();
return this.operations.getRemainingOperationsCount();
} else {
this._logger.info(
@@ -196,6 +201,15 @@ export class IssuesProcessor {
)}`
);
if (this.state.isIssueProcessed(issue)) {
issueLogger.info(
' $$type skipped due being processed during the previous run'
);
return;
}
this.state.addIssueToProcessed(issue);
// calculate string based messages for this issue
const staleMessage: string = issue.isPullRequest
? this.options.stalePrMessage

69
src/classes/state.ts Normal file
View File

@@ -0,0 +1,69 @@
import {Issue} from './issue';
import {IState} from '../interfaces/state';
import os from 'os';
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
import artifact from '@actions/artifact';
type IssueID = number;
export class State implements IState {
private processedIssuesIDs: Set<IssueID>;
constructor() {
this.processedIssuesIDs = new Set();
}
isIssueProcessed(issue: Issue) {
return this.processedIssuesIDs.has(issue.number);
}
addIssueToProcessed(issue: Issue) {
this.processedIssuesIDs.add(issue.number);
}
reset() {
this.processedIssuesIDs.clear();
}
private static readonly ARTIFACT_NAME = '_stale_state';
async persist() {
const serialized = Array.from(this.processedIssuesIDs).join('|');
const tmpDir = os.tmpdir();
const file = crypto.randomBytes(8).readBigUInt64LE(0).toString();
fs.writeFileSync(path.join(tmpDir, file), serialized);
const artifactClient = artifact.create();
// TODO: handle errors
await artifactClient.uploadArtifact(State.ARTIFACT_NAME, [file], tmpDir);
}
async rehydrate() {
this.reset();
const tmpDir = os.tmpdir();
const artifactClient = artifact.create();
const downloadResponse = await artifactClient.downloadArtifact(
State.ARTIFACT_NAME,
tmpDir
);
const downloadedFiles = fs.readdirSync(downloadResponse.downloadPath);
if (downloadedFiles.length === 0) {
// TODO: handle error
}
const serialized = fs.readFileSync(
path.join(downloadResponse.downloadPath, downloadedFiles[0]),
{encoding: 'utf8'}
);
if (serialized.length === 0) return;
const issueIDs = serialized
.split('|')
.map(parseInt)
.filter(i => !isNaN(i));
this.processedIssuesIDs = new Set(issueIDs);
}
}