Circle ci fixes automated build (#23373)
* Lessons learned from using circle-ci 1. Make it clearer that GITHUB_TOKEN or GITHUB_ACCESS_TOKEN are required for a release. Don't build without them. 2. Default gracefully to an reasonable email address. (It does not have to actually exist, but the api needs it to publish) * template for testing * Wrote a basic test. * Simple test * Slight fix to brackets * Code review changes * Fix for test. Setup environment properly
This commit is contained in:
@@ -4,10 +4,16 @@ const fs = require('fs');
|
|||||||
|
|
||||||
entrypoint = () => {
|
entrypoint = () => {
|
||||||
const defaultEntryPoint = '../src/cli/index.js';
|
const defaultEntryPoint = '../src/cli/index.js';
|
||||||
// We are running in dev mode. Don't use compiled binaries, rather use the dev entrypoint.
|
const toolkitDirectory = `${process.env['PWD']}/node_modules/@grafana/toolkit`;
|
||||||
if (fs.existsSync(`${process.env['HOME']}/.config/yarn/link/@grafana/toolkit`)) {
|
|
||||||
console.log('Running in linked mode');
|
// IF we have a toolkit directory AND linked grafana toolkit AND the toolkit dir is a symbolic lik
|
||||||
return `${__dirname}/grafana-toolkit.js`;
|
// THEN run everything in linked mode
|
||||||
|
if (fs.existsSync(toolkitDirectory)) {
|
||||||
|
const tkStat = fs.lstatSync(toolkitDirectory);
|
||||||
|
if (fs.existsSync(`${process.env['HOME']}/.config/yarn/link/@grafana/toolkit`) && tkStat.isSymbolicLink()) {
|
||||||
|
console.log('Running in linked mode');
|
||||||
|
return `${__dirname}/grafana-toolkit.js`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are using npx, and a relative path does not find index.js
|
// We are using npx, and a relative path does not find index.js
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import path = require('path');
|
|||||||
import execa = require('execa');
|
import execa = require('execa');
|
||||||
|
|
||||||
interface Command extends Array<any> {}
|
interface Command extends Array<any> {}
|
||||||
|
const DEFAULT_EMAIL_ADDRESS = 'eng@graafna.com';
|
||||||
|
const DEFAULT_USERNAME = 'CircleCI Automation';
|
||||||
|
|
||||||
const releaseNotes = async (): Promise<string> => {
|
const releaseNotes = async (): Promise<string> => {
|
||||||
const { stdout } = await execa.shell(`awk \'BEGIN {FS="##"; RS=""} FNR==3 {print; exit}\' CHANGELOG.md`);
|
const { stdout } = await execa.shell(`awk \'BEGIN {FS="##"; RS=""} FNR==3 {print; exit}\' CHANGELOG.md`);
|
||||||
@@ -62,12 +64,10 @@ const prepareRelease = useSpinner<any>('Preparing release', async ({ dryrun, ver
|
|||||||
const distContentDir = path.resolve(distDir, getPluginId());
|
const distContentDir = path.resolve(distDir, getPluginId());
|
||||||
const pluginJsonFile = path.resolve(distContentDir, 'plugin.json');
|
const pluginJsonFile = path.resolve(distContentDir, 'plugin.json');
|
||||||
const pluginJson = getPluginJson(pluginJsonFile);
|
const pluginJson = getPluginJson(pluginJsonFile);
|
||||||
const GIT_EMAIL = 'eng@grafana.com';
|
|
||||||
const GIT_USERNAME = 'CircleCI Automation';
|
|
||||||
|
|
||||||
const githubPublishScript: Command = [
|
const githubPublishScript: Command = [
|
||||||
['git', ['config', 'user.email', GIT_EMAIL]],
|
['git', ['config', 'user.email', DEFAULT_EMAIL_ADDRESS]],
|
||||||
['git', ['config', 'user.name', GIT_USERNAME]],
|
['git', ['config', 'user.name', DEFAULT_USERNAME]],
|
||||||
await checkoutBranch(`release-${pluginJson.info.version}`),
|
await checkoutBranch(`release-${pluginJson.info.version}`),
|
||||||
['cp', ['-rf', distContentDir, 'dist']],
|
['cp', ['-rf', distContentDir, 'dist']],
|
||||||
['git', ['add', '--force', distDir], { dryrun }],
|
['git', ['add', '--force', distDir], { dryrun }],
|
||||||
@@ -138,14 +138,14 @@ const prepareRelease = useSpinner<any>('Preparing release', async ({ dryrun, ver
|
|||||||
interface GithubPublishReleaseOptions {
|
interface GithubPublishReleaseOptions {
|
||||||
commitHash?: string;
|
commitHash?: string;
|
||||||
githubToken: string;
|
githubToken: string;
|
||||||
gitRepoOwner: string;
|
githubEmail: string;
|
||||||
gitRepoName: string;
|
gitRepoName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createRelease = useSpinner<GithubPublishReleaseOptions>(
|
const createRelease = useSpinner<GithubPublishReleaseOptions>(
|
||||||
'Creating release',
|
'Creating release',
|
||||||
async ({ commitHash, githubToken, gitRepoName, gitRepoOwner }) => {
|
async ({ commitHash, githubEmail, githubToken, gitRepoName }) => {
|
||||||
const gitRelease = new GitHubRelease(githubToken, gitRepoOwner, gitRepoName, await releaseNotes(), commitHash);
|
const gitRelease = new GitHubRelease(githubToken, githubEmail, gitRepoName, await releaseNotes(), commitHash);
|
||||||
return gitRelease.release();
|
return gitRelease.release();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -159,16 +159,31 @@ export interface GithubPublishOptions {
|
|||||||
|
|
||||||
const githubPublishRunner: TaskRunner<GithubPublishOptions> = async ({ dryrun, verbose, commitHash }) => {
|
const githubPublishRunner: TaskRunner<GithubPublishOptions> = async ({ dryrun, verbose, commitHash }) => {
|
||||||
if (!process.env['CIRCLE_REPOSITORY_URL']) {
|
if (!process.env['CIRCLE_REPOSITORY_URL']) {
|
||||||
throw `The release plugin requires you specify the repository url as environment variable CIRCLE_REPOSITORY_URL`;
|
throw new Error(
|
||||||
|
'The release plugin requires you specify the repository url as environment variable CIRCLE_REPOSITORY_URL'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process.env['GITHUB_TOKEN']) {
|
if (!process.env['GITHUB_ACCESS_TOKEN']) {
|
||||||
throw `Github publish requires that you set the environment variable GITHUB_TOKEN to a valid github api token.
|
// Try to use GITHUB_TOKEN, which may be set.
|
||||||
See: https://github.com/settings/tokens for more details.`;
|
if (process.env['GITHUB_TOKEN']) {
|
||||||
|
process.env['GITHUB_ACCESS_TOKEN'] = process.env['GITHUB_TOKEN'];
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`Github publish requires that you set the environment variable GITHUB_ACCESS_TOKEN to a valid github api token.
|
||||||
|
See: https://github.com/settings/tokens for more details.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!process.env['GITHUB_USERNAME']) {
|
||||||
|
// We can default this one
|
||||||
|
process.env['GITHUB_USERNAME'] = DEFAULT_EMAIL_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedUrl = gitUrlParse(process.env['CIRCLE_REPOSITORY_URL']);
|
const parsedUrl = gitUrlParse(process.env['CIRCLE_REPOSITORY_URL']);
|
||||||
const githubToken = process.env['GITHUB_TOKEN'];
|
const githubToken = process.env['GITHUB_ACCESS_TOKEN'];
|
||||||
|
const githubEmail = process.env['GITHUB_USERNAME'];
|
||||||
|
|
||||||
await prepareRelease({
|
await prepareRelease({
|
||||||
dryrun,
|
dryrun,
|
||||||
@@ -177,8 +192,8 @@ const githubPublishRunner: TaskRunner<GithubPublishOptions> = async ({ dryrun, v
|
|||||||
|
|
||||||
await createRelease({
|
await createRelease({
|
||||||
commitHash,
|
commitHash,
|
||||||
|
githubEmail,
|
||||||
githubToken,
|
githubToken,
|
||||||
gitRepoOwner: parsedUrl.owner,
|
|
||||||
gitRepoName: parsedUrl.name,
|
gitRepoName: parsedUrl.name,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { GitHubRelease } from './githubRelease';
|
||||||
|
|
||||||
|
describe('GithubRelease', () => {
|
||||||
|
it('should initialise a GithubRelease', () => {
|
||||||
|
process.env.GITHUB_ACCESS_TOKEN = '12345';
|
||||||
|
process.env.GITHUB_USERNAME = 'test@grafana.com';
|
||||||
|
const github = new GitHubRelease('A token', 'A username', 'A repo', 'Some release notes');
|
||||||
|
expect(github).toBeInstanceOf(GitHubRelease);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -37,6 +37,7 @@ class GitHubRelease {
|
|||||||
this.commitHash = commitHash;
|
this.commitHash = commitHash;
|
||||||
|
|
||||||
this.git = new GithubClient({
|
this.git = new GithubClient({
|
||||||
|
required: true,
|
||||||
repo: repository,
|
repo: repository,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -97,7 +98,9 @@ class GitHubRelease {
|
|||||||
`https://uploads.github.com/repos/${this.username}/${this.repository}/releases/${newReleaseResponse.data.id}/assets`
|
`https://uploads.github.com/repos/${this.username}/${this.repository}/releases/${newReleaseResponse.data.id}/assets`
|
||||||
);
|
);
|
||||||
} catch (reason) {
|
} catch (reason) {
|
||||||
console.error('error', reason);
|
console.error(reason.data?.message ?? reason);
|
||||||
|
// Rethrow the error so that we can trigger a non-zero exit code to circle-ci
|
||||||
|
throw reason;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user