Skip to content

Commit

Permalink
chore: add renovate APIC-490 (#522)
Browse files Browse the repository at this point in the history
  • Loading branch information
millotp authored May 20, 2022
1 parent 4091c4d commit 7d14296
Show file tree
Hide file tree
Showing 15 changed files with 268 additions and 34 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ jobs:
exit $diff
- name: Lint json files
run: yarn eslint --ext=json .
run: |
yarn eslint --ext=json .
echo 'Use yarn fix:json to fix issues'
outputs:
RUN_SCRIPTS: ${{ steps.setup.outputs.RUN_SCRIPTS }}
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/renovate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Renovate

on:
schedule:
- cron: '0 14 * * 5'

jobs:
renovate:
name: Renovate
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2

- name: Setup
id: setup
uses: ./.github/actions/setup
with:
type: minimal

- run: yarn workspace scripts renovateWeeklyPR
env:
GITHUB_TOKEN: ${{ secrets.TOKEN_RELEASE_BOT }}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"mustache": "4.2.0",
"prettier": "2.6.2",
"prettier-plugin-java": "1.6.1",
"renovate-config-algolia": "2.1.10",
"typescript": "4.6.3"
},
"engines": {
Expand Down
23 changes: 23 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"extends": [
"config:js-app",
"algolia"
],
"enabledManagers": [
"npm",
"nvm"
],
"baseBranches": [
"chore/renovateBaseBranch"
],
"packageRules": [
{
"matchDepTypes": [
"required_provider"
],
"rangeStrategy": "bump"
}
],
"prHourlyLimit": 10,
"prConcurrentLimit": 50
}
7 changes: 5 additions & 2 deletions scripts/ci/codegen/__tests__/codegen.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,18 @@ describe('codegen', () => {

describe('pushGeneratedCode', () => {
it('throws without GITHUB_TOKEN environment variable', async () => {
process.env.GITHUB_TOKEN = '';
await expect(pushGeneratedCode()).rejects.toThrow(
'Environment variable `GITHUB_TOKEN` does not exist.'
);
});
});

describe('upsertGenerationComment', () => {
beforeAll(() => {
process.env.GITHUB_TOKEN = 'mocked';
});

it('throws without parameter', async () => {
await expect(
// @ts-expect-error a parameter is required
Expand All @@ -38,8 +43,6 @@ describe('codegen', () => {
});

it('throws without PR_NUMBER environment variable', async () => {
process.env.GITHUB_TOKEN = 'foo';

await expect(upsertGenerationComment('codegen')).rejects.toThrow(
'`upsertGenerationComment` requires a `PR_NUMBER` environment variable.'
);
Expand Down
6 changes: 2 additions & 4 deletions scripts/ci/codegen/pushGeneratedCode.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-console */
import { MAIN_BRANCH, run } from '../../common';
import { ensureGitHubToken, MAIN_BRANCH, run } from '../../common';
import { configureGitHubAuthor } from '../../release/common';
import { getNbGitDiff } from '../utils';

Expand All @@ -18,9 +18,7 @@ async function isUpToDate(baseBranch: string): Promise<boolean> {
* Push generated code for the current `JOB` and `CLIENT` on a `generated/` branch.
*/
export async function pushGeneratedCode(): Promise<void> {
if (!process.env.GITHUB_TOKEN) {
throw new Error('Environment variable `GITHUB_TOKEN` does not exist.');
}
ensureGitHubToken();

await configureGitHubAuthor();

Expand Down
7 changes: 3 additions & 4 deletions scripts/ci/codegen/spreadGeneration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
run,
toAbsolutePath,
REPO_URL,
ensureGitHubToken,
} from '../../common';
import { getLanguageFolder } from '../../config';
import { cloneRepository, configureGitHubAuthor } from '../../release/common';
Expand Down Expand Up @@ -60,9 +61,7 @@ export function cleanUpCommitMessage(commitMessage: string): string {
}

async function spreadGeneration(): Promise<void> {
if (!process.env.GITHUB_TOKEN) {
throw new Error('Environment variable `GITHUB_TOKEN` does not exist.');
}
const githubToken = ensureGitHubToken();

const lastCommitMessage = await run('git log -1 --format="%s"');
const author = (
Expand All @@ -81,7 +80,7 @@ async function spreadGeneration(): Promise<void> {
for (const lang of langs) {
const { tempGitDir } = await cloneRepository({
lang,
githubToken: process.env.GITHUB_TOKEN,
githubToken,
tempDir: process.env.RUNNER_TEMP!,
});

Expand Down
5 changes: 2 additions & 3 deletions scripts/ci/codegen/upsertGenerationComment.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
/* eslint-disable no-console */
import { run, OWNER, REPO } from '../../common';
import { getOctokit } from '../../release/common';
import { run, OWNER, REPO, getOctokit } from '../../common';

import commentText from './text';

const BOT_NAME = 'algolia-bot';
const PR_NUMBER = parseInt(process.env.PR_NUMBER || '0', 10);
const octokit = getOctokit(process.env.GITHUB_TOKEN!);

const args = process.argv.slice(2);
const allowedTriggers = [
Expand Down Expand Up @@ -47,6 +45,7 @@ ${commentText[trigger].body(
* Adds or updates a comment on a pull request.
*/
export async function upsertGenerationComment(trigger: Trigger): Promise<void> {
const octokit = getOctokit();
if (!trigger || allowedTriggers.includes(trigger) === false) {
throw new Error(
`'upsertGenerationComment' requires a 'trigger' parameter (${allowedTriggers.join(
Expand Down
162 changes: 162 additions & 0 deletions scripts/ci/githubActions/renovateWeeklyPR.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/* eslint-disable no-console */
// script coming from crawler <3
import type { Octokit } from '@octokit/rest';

import { getOctokit, OWNER, REPO, wait } from '../../common';

const BRANCH = 'chore/renovateBaseBranch';
const BRANCH_BASE = 'main';
const EMPTY_COMMIT_MSG = 'Automatic empty commit';

async function getRef(
octokit: Octokit,
branch: string
): Promise<string | false> {
try {
const ref = await octokit.git.getRef({
owner: OWNER,
repo: REPO,
ref: `heads/${branch}`,
});
return ref.data.object.sha;
} catch (err) {
if (!(err instanceof Error) || (err as any).status !== 404) {
throw err;
}
}
return false;
}

async function createBranch(octokit: Octokit, sha: string): Promise<any> {
const create = await octokit.git.createRef({
owner: OWNER,
repo: REPO,
ref: `refs/heads/${BRANCH}`,
sha,
});
return create;
}

async function deleteRef(octokit: Octokit): Promise<any> {
console.log(`Deleting ref for ${BRANCH}`);
const ref = await octokit.git.deleteRef({
owner: OWNER,
repo: REPO,
ref: `heads/${BRANCH}`,
});
return ref;
}

async function updateRef(octokit: Octokit, sha: string): Promise<any> {
console.log(`Changing ref for ${BRANCH} to`, sha);
const ref = await octokit.git.updateRef({
owner: OWNER,
repo: REPO,
ref: `heads/${BRANCH}`,
sha,
});
return ref;
}

async function getCommit(octokit: Octokit, sha: string): Promise<any> {
const commit = await octokit.git.getCommit({
owner: OWNER,
repo: REPO,
commit_sha: sha,
});
return commit.data;
}

function isCommitAnEmptyCommit(commit: any): boolean {
return commit.message.search(EMPTY_COMMIT_MSG) >= 0;
}

async function createEmptyCommit(
octokit: Octokit,
refCommit: any
): Promise<any> {
console.log('Creating empty commit');
const commit = await octokit.git.createCommit({
owner: OWNER,
repo: REPO,
message: EMPTY_COMMIT_MSG,
tree: refCommit.tree.sha,
parents: [refCommit.sha],
});
return commit.data;
}

async function createPR(octokit: Octokit): Promise<any> {
// Next monday
const date = new Date();
date.setDate(date.getDate() + 3);

const title = `chore(scripts): dependencies ${
date.toISOString().split('T')[0]
}`;
const { data } = await octokit.pulls.create({
repo: REPO,
owner: OWNER,
title,
body: `Weekly dependencies update.
Contributes to #528
`,
head: BRANCH,
base: BRANCH_BASE,
});
return data;
}

async function resetBranch(
octokit: Octokit,
refBase: string,
exists: boolean
): Promise<void> {
if (exists) {
console.log('Deleting branch');
await deleteRef(octokit);
await wait(5000);
}

console.log('Creating branch');

await createBranch(octokit, refBase);

const commit = await getCommit(octokit, refBase);

const empty = await createEmptyCommit(octokit, commit);
await updateRef(octokit, empty.sha);
}

(async (): Promise<void> => {
try {
const octokit = getOctokit();

const refBase = await getRef(octokit, BRANCH_BASE);
const refTarget = await getRef(octokit, BRANCH);
console.log(BRANCH_BASE, 'is at', refBase);
console.log(BRANCH, 'is at', refTarget);

if (!refBase) {
console.error('no sha for base branch');
return;
}

if (refTarget) {
console.log('Branch exists');
const commit = await getCommit(octokit, refTarget);

if (isCommitAnEmptyCommit(commit)) {
console.log('Empty commit exists');
return;
}
}

await resetBranch(octokit, refBase, Boolean(refTarget));

console.log('Creating pull request');
await createPR(octokit);
} catch (err) {
console.error(err);
}
})();
25 changes: 25 additions & 0 deletions scripts/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fsp from 'fs/promises';
import path from 'path';

import { Octokit } from '@octokit/rest';
import execa from 'execa'; // https://github.com/sindresorhus/execa/tree/v5.1.1
import { hashElement } from 'folder-hash';
import { remove } from 'fs-extra';
Expand Down Expand Up @@ -258,3 +259,27 @@ export async function runComposerUpdate(verbose: boolean): Promise<void> {
);
}
}

export function ensureGitHubToken(): string {
// use process.env here to mock with jest
if (!process.env.GITHUB_TOKEN) {
throw new Error('Environment variable `GITHUB_TOKEN` does not exist.');
}
return process.env.GITHUB_TOKEN;
}

export function getOctokit(): Octokit {
const token = ensureGitHubToken();
return new Octokit({
auth: `token ${token}`,
});
}

export function wait(waitTime: number): Promise<void> {
if (waitTime <= 0) {
return Promise.resolve();
}
return new Promise((resolve) => {
setTimeout(resolve, waitTime);
});
}
1 change: 1 addition & 0 deletions scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"pre-commit": "./ci/husky/pre-commit.js",
"processRelease": "ts-node release/process-release.ts",
"pushGeneratedCode": "ts-node ci/codegen/pushGeneratedCode.ts",
"renovateWeeklyPR": "ts-node ci/githubActions/renovateWeeklyPR.ts",
"setRunVariables": "ts-node ci/githubActions/setRunVariables.ts",
"spreadGeneration": "ts-node ci/codegen/spreadGeneration.ts",
"test": "jest",
Expand Down
8 changes: 0 additions & 8 deletions scripts/release/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import path from 'path';

import { Octokit } from '@octokit/rest';

import config from '../../config/release.config.json';
import { run } from '../common';
import { getGitHubUrl } from '../config';
Expand All @@ -10,12 +8,6 @@ import type { Language } from '../types';
export const RELEASED_TAG = config.releasedTag;
export const TEAM_SLUG = config.teamSlug;

export function getOctokit(githubToken: string): Octokit {
return new Octokit({
auth: `token ${githubToken}`,
});
}

export function getTargetBranch(language: string): string {
return config.targetBranch[language] || config.defaultTargetBranch;
}
Expand Down
Loading

0 comments on commit 7d14296

Please sign in to comment.