Skip to content

Commit

Permalink
chore: improve random cron generation
Browse files Browse the repository at this point in the history
  • Loading branch information
xiehan committed Apr 5, 2024
1 parent 7b8907d commit 3b0e95b
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions src/alert-open-prs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { cdk } from "projen";
import { GithubWorkflow } from "projen/lib/github";
import { JobPermission } from "projen/lib/github/workflows-model";
import { generateRandomCron, Schedule } from "./util/random-cron";

const DEFAULT_MAX_HOURS_OPEN = 2;

Expand All @@ -25,8 +26,17 @@ export class AlertOpenPrs {

const workflow = new GithubWorkflow(project.github!, "alert-open-prs");
workflow.on({
workflowDispatch: {},
schedule: [{ cron: "* */12 * * 1-5" }], // every 12 hours, Monday-Friday
// run on weekdays sometime during working hours (8am-4pm UTC)
schedule: [
{
cron: generateRandomCron({
project,
maxHour: 8,
hourOffset: 8,
schedule: Schedule.Weekdays,
}),
},
],
});
workflow.addJob("check-open-prs", {
runsOn: ["ubuntu-latest"],
Expand Down
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { PackageInfo } from "./package-info";
import { ProviderUpgrade } from "./provider-upgrade";
import { CheckForUpgradesScriptFile } from "./scripts/check-for-upgrades";
import { ShouldReleaseScriptFile } from "./scripts/should-release";
import { generateRandomCron } from "./util/random-cron";

// ensure new projects start with 1.0.0 so that every following breaking change leads to an increased major version
const MIN_MAJOR_VERSION = 1;
Expand Down Expand Up @@ -450,6 +451,13 @@ export class CdktfProviderProject extends cdk.JsiiProject {
" or cancel via faking a SHA if release was cancelled";
}

const staleWorkflow = this.tryFindObjectFile(".github/workflows/stale.yml");
staleWorkflow?.addOverride("on.schedule", [
{
cron: generateRandomCron({ project: this, maxHour: 4, hourOffset: 1 }),
},
]);

// Submodule documentation generation
this.gitignore.exclude("API.md"); // ignore the old file, we now generate it in the docs folder
this.addDevDeps("jsii-docgen@^10.2.3");
Expand Down
11 changes: 3 additions & 8 deletions src/lock-issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
* SPDX-License-Identifier: MPL-2.0
*/

import { createHash } from "crypto";
import { javascript } from "projen";
import { JobPermission } from "projen/lib/github/workflows-model";
import { generateRandomCron } from "./util/random-cron";

/**
* Automatically locks issues and PRs after 7 days. Note that 90% of the issues and PRs
Expand All @@ -18,14 +18,9 @@ export class LockIssues {

if (!workflow) throw new Error("no workflow defined");

const projectNameHash = createHash("md5")
.update(project.name)
.digest("hex");
const scheduleHour = parseInt(projectNameHash.slice(0, 2), 16) % 24;
const scheduleMinute = parseInt(projectNameHash.slice(2, 4), 16) % 24;

workflow.on({
schedule: [{ cron: `${scheduleHour} ${scheduleMinute} * * *` }],
// run daily sometime between midnight and 6am UTC
schedule: [{ cron: generateRandomCron({ project, maxHour: 6 }) }],
});

workflow.addJob("lock", {
Expand Down
42 changes: 42 additions & 0 deletions src/util/random-cron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import { createHash } from "crypto";
import { javascript } from "projen";

export enum Schedule {
Daily = "DAILY",
Weekly = "WEEKLY",
Monthly = "MONTHLY",
Weekdays = "WEEKDAYS",
}

export interface RandomCronOptions {
project: javascript.NodeProject;
maxHour?: number;
hourOffset?: number;
schedule?: Schedule;
}

export function generateRandomCron(options: RandomCronOptions) {
const maxHour = options.maxHour ? Math.round(options.maxHour) : 24;
const hourOffset = options.hourOffset ? Math.round(options.hourOffset) : 0;
const schedule = options.schedule || Schedule.Daily; // default to daily

const project = options.project;
const hash = createHash("md5").update(project.name).digest("hex");
const hour = maxHour === 0 ? 0 : parseInt(hash.slice(0, 2), 16) % maxHour;
const minute = parseInt(hash.slice(2, 4), 16) % 60;

const dayOfMonth = schedule === Schedule.Monthly ? "1" : "*";
const dayOfWeek =
schedule === Schedule.Weekly
? "1"
: schedule === Schedule.Weekdays
? "1-5"
: "*";

return `${minute} ${(hour + hourOffset) % 24} ${dayOfMonth} * ${dayOfWeek}`;
}
32 changes: 14 additions & 18 deletions test/__snapshots__/index.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3b0e95b

Please sign in to comment.