diff --git a/lerna.json b/lerna.json index 1fa5994e34ffe..f72b0b06cd2eb 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "npmClient": "yarn", "useWorkspaces": true, "packages": ["packages/*"], - "version": "6.4.0-alpha.6" + "version": "6.4.0-alpha.12" } diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 73bbc12c020ea..7163c62f4f96b 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/data", - "version": "6.4.0-alpha.2", + "version": "6.4.0-alpha.12", "description": "Grafana Data Library", "keywords": [ "typescript" diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index 7905da52922ce..d3ef30c938ffb 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/runtime", - "version": "6.4.0-alpha.2", + "version": "6.4.0-alpha.12", "description": "Grafana Runtime Library", "keywords": [ "grafana" diff --git a/packages/grafana-toolkit/package.json b/packages/grafana-toolkit/package.json index 78f8438ba56b4..d28e3b4d41fa4 100644 --- a/packages/grafana-toolkit/package.json +++ b/packages/grafana-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/toolkit", - "version": "6.4.0-alpha.6", + "version": "6.4.0-alpha.12", "description": "Grafana Toolkit", "keywords": [ "grafana", diff --git a/packages/grafana-toolkit/src/cli/index.ts b/packages/grafana-toolkit/src/cli/index.ts index ab9efadae4045..a8997eba5cbeb 100644 --- a/packages/grafana-toolkit/src/cli/index.ts +++ b/packages/grafana-toolkit/src/cli/index.ts @@ -15,10 +15,11 @@ import { closeMilestoneTask } from './tasks/closeMilestone'; import { pluginDevTask } from './tasks/plugin.dev'; import { ciBuildPluginTask, + ciBuildPluginDocsTask, ciBundlePluginTask, ciTestPluginTask, + ciPluginReportTask, ciDeployPluginTask, - ciSetupPluginTask, } from './tasks/plugin.ci'; import { buildPackageTask } from './tasks/package.build'; @@ -148,39 +149,45 @@ export const run = (includeInternalScripts = false) => { program .command('plugin:ci-build') - .option('--platform ', 'For backend task, which backend to run') + .option('--backend ', 'For backend task, which backend to run') .description('Build the plugin, leaving artifacts in /dist') .action(async cmd => { await execTask(ciBuildPluginTask)({ - platform: cmd.platform, + backend: cmd.backend, }); }); program - .command('plugin:ci-bundle') - .description('Create a zip artifact for the plugin') + .command('plugin:ci-docs') + .description('Build the HTML docs') .action(async cmd => { - await execTask(ciBundlePluginTask)({}); + await execTask(ciBuildPluginDocsTask)({}); }); program - .command('plugin:ci-setup') - .option('--installer ', 'Name of installer to download and run') - .description('Install and configure grafana') + .command('plugin:ci-bundle') + .description('Create a zip artifact for the plugin') .action(async cmd => { - await execTask(ciSetupPluginTask)({ - installer: cmd.installer, - }); + await execTask(ciBundlePluginTask)({}); }); + program .command('plugin:ci-test') + .option('--full', 'run all the tests (even stuff that will break)') .description('end-to-end test using bundle in /artifacts') .action(async cmd => { await execTask(ciTestPluginTask)({ - platform: cmd.platform, + full: cmd.full, }); }); + program + .command('plugin:ci-report') + .description('Build a report for this whole process') + .action(async cmd => { + await execTask(ciPluginReportTask)({}); + }); + program .command('plugin:ci-deploy') .description('Publish plugin CI results') diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts index 71cbe4eb20deb..85f4313aa60c2 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts @@ -9,8 +9,8 @@ import path = require('path'); import fs = require('fs'); export interface PluginCIOptions { - platform?: string; - installer?: string; + backend?: string; + full?: boolean; } const calcJavascriptSize = (base: string, files?: string[]): number => { @@ -48,32 +48,6 @@ const getJobFromProcessArgv = () => { return 'unknown_job'; }; -// /** -// * Like cp -rn... BUT error if an destination file exists -// */ -// async function copyDirErrorIfExists(src:string,dest:string) { -// const entries = await fs.readdirSync(src,{withFileTypes:true}); -// if(!fs.existsSync(dest)) { -// fs.mkdirSync(dest); -// } -// console.log( 'DIR', src ); -// for(let entry of entries) { -// const srcPath = path.join(src,entry.name); -// const destPath = path.join(dest,entry.name); -// if(entry.isDirectory()) { -// await copyDirErrorIfExists(srcPath,destPath); -// } else if(fs.existsSync(destPath)) { -// console.log( 'XXXXXXXXXXXXXXX', destPath ); -// console.log( 'XXXXXXXXXXXXXXX', destPath ); -// throw new Error('Duplicate entry: '+destPath); -// } -// else { -// // console.log( 'COPY', destPath ); -// await fs.copyFileSync(srcPath,destPath); -// } -// } -// } - const job = process.env.CIRCLE_JOB || getJobFromProcessArgv(); const getJobFolder = () => { @@ -117,17 +91,17 @@ const writeJobStats = (startTime: number, workDir: string) => { * Anything that should be put into the final zip file should be put in: * ~/work/build_xxx/dist */ -const buildPluginRunner: TaskRunner = async ({ platform }) => { +const buildPluginRunner: TaskRunner = async ({ backend }) => { const start = Date.now(); const workDir = getJobFolder(); await execa('rimraf', [workDir]); fs.mkdirSync(workDir); - if (platform) { + if (backend) { console.log('TODO, backend support?'); fs.mkdirSync(path.resolve(process.cwd(), 'dist')); - const file = path.resolve(process.cwd(), 'dist', `README_${platform}.txt`); - fs.writeFile(file, `TODO... build ${platform}!`, err => { + const file = path.resolve(process.cwd(), 'dist', `README_${backend}.txt`); + fs.writeFile(file, `TODO... build bakend plugin: ${backend}!`, err => { if (err) { throw new Error('Unable to write: ' + file); } @@ -149,6 +123,40 @@ const buildPluginRunner: TaskRunner = async ({ platform }) => { export const ciBuildPluginTask = new Task('Build Plugin', buildPluginRunner); +/** + * 2. Build Docs + * + * Take /docs/* and format it into /ci/docs/HTML site + * + */ +const buildPluginDocsRunner: TaskRunner = async () => { + const docsSrc = path.resolve(process.cwd(), 'docs'); + if (!fs.existsSync(docsSrc)) { + throw new Error('Docs folder does not exist!'); + } + + const start = Date.now(); + const workDir = getJobFolder(); + await execa('rimraf', [workDir]); + fs.mkdirSync(workDir); + + const docsDest = path.resolve(process.cwd(), 'ci', 'docs'); + fs.mkdirSync(docsDest); + + const exe = await execa('cp', ['-rv', docsSrc + '/.', docsDest]); + console.log(exe.stdout); + + fs.writeFile(path.resolve(docsDest, 'index.html'), `TODO... actually build docs`, err => { + if (err) { + throw new Error('Unable to docs'); + } + }); + + writeJobStats(start, workDir); +}; + +export const ciBuildPluginDocsTask = new Task('Build Plugin Docs', buildPluginDocsRunner); + /** * 2. BUNDLE * @@ -163,6 +171,7 @@ const bundlePluginRunner: TaskRunner = async () => { const ciDir = getCiFolder(); const artifactsDir = path.resolve(ciDir, 'artifacts'); const distDir = path.resolve(ciDir, 'dist'); + const docsDir = path.resolve(ciDir, 'docs'); const grafanaEnvDir = path.resolve(ciDir, 'grafana-test-env'); await execa('rimraf', [artifactsDir, distDir, grafanaEnvDir]); fs.mkdirSync(artifactsDir); @@ -192,8 +201,8 @@ const bundlePluginRunner: TaskRunner = async () => { console.log('Building ZIP'); const pluginInfo = getPluginJson(`${distDir}/plugin.json`); - const zipName = pluginInfo.id + '-' + pluginInfo.info.version + '.zip'; - const zipFile = path.resolve(artifactsDir, zipName); + let zipName = pluginInfo.id + '-' + pluginInfo.info.version + '.zip'; + let zipFile = path.resolve(artifactsDir, zipName); process.chdir(distDir); await execa('zip', ['-r', zipFile, '.']); restoreCwd(); @@ -202,21 +211,49 @@ const bundlePluginRunner: TaskRunner = async () => { if (zipStats.size < 100) { throw new Error('Invalid zip file: ' + zipFile); } - let sha1 = undefined; + + const zipInfo: any = { + name: zipName, + size: zipStats.size, + }; + const info: any = { + plugin: zipInfo, + }; try { const exe = await execa('shasum', [zipFile]); const idx = exe.stdout.indexOf(' '); - sha1 = exe.stdout.substring(0, idx); + const sha1 = exe.stdout.substring(0, idx); fs.writeFile(zipFile + '.sha1', sha1, err => {}); + zipInfo.sha1 = sha1; } catch { console.warn('Unable to read SHA1 Checksum'); } - const info = { - name: zipName, - sha1, - size: zipStats.size, - }; + // If docs exist, zip them into artifacts + if (fs.existsSync(docsDir)) { + zipName = pluginInfo.id + '-' + pluginInfo.info.version + '-docs.zip'; + zipFile = path.resolve(artifactsDir, zipName); + process.chdir(docsDir); + await execa('zip', ['-r', zipFile, '.']); + restoreCwd(); + + const zipStats = fs.statSync(zipFile); + const zipInfo: any = { + name: zipName, + size: zipStats.size, + }; + try { + const exe = await execa('shasum', [zipFile]); + const idx = exe.stdout.indexOf(' '); + const sha1 = exe.stdout.substring(0, idx); + fs.writeFile(zipFile + '.sha1', sha1, err => {}); + zipInfo.sha1 = sha1; + } catch { + console.warn('Unable to read SHA1 Checksum'); + } + info.docs = zipInfo; + } + let p = path.resolve(artifactsDir, 'info.json'); fs.writeFile(p, JSON.stringify(info, null, 2), err => { if (err) { @@ -248,66 +285,15 @@ const bundlePluginRunner: TaskRunner = async () => { export const ciBundlePluginTask = new Task('Bundle Plugin', bundlePluginRunner); /** - * 3. Setup (install grafana and setup provisioning) - * - * deploy the zip to a running grafana instance - * - */ -const setupPluginRunner: TaskRunner = async ({ installer }) => { - const start = Date.now(); - - if (!installer) { - throw new Error('Missing installer path'); - } - - // Download the grafana installer - const installDir = path.resolve(process.cwd(), '.installer'); - const installFile = path.resolve(installDir, installer); - if (!fs.existsSync(installFile)) { - if (!fs.existsSync(installDir)) { - fs.mkdirSync(installDir); - } - console.log('download', installer); - const exe = await execa('wget', ['-O', installFile, 'https://dl.grafana.com/oss/release/' + installer]); - console.log(exe.stdout); - } - - console.log('Install Grafana'); - let exe = await execa('sudo', ['apt-get', 'install', '-y', 'adduser', 'libfontconfig1']); - exe = await execa('sudo', ['dpkg', '-i', installFile]); - console.log(exe.stdout); - - const customIniFile = path.resolve(getCiFolder(), 'grafana-test-env', 'custom.ini'); - const configDir = '/usr/share/grafana/conf/'; - exe = await execa('sudo', ['cp', '-f', customIniFile, configDir]); - console.log(exe.stdout); - - // sudo service grafana-server start - console.log('Starting Grafana'); - exe = await execa('sudo', ['service', 'grafana-server', 'start']); - console.log(exe.stdout); - // exe = await execa('grafana-cli', ['--version', '--homepath', '/usr/share/grafana']); - // console.log(exe.stdout); - // exe = await execa('grafana-cli', ['plugins', 'ls', '--homepath', '/usr/share/grafana']); - // console.log(exe.stdout); - - const dir = getJobFolder() + '_setup'; - await execa('rimraf', [dir]); - fs.mkdirSync(dir); - writeJobStats(start, dir); -}; - -export const ciSetupPluginTask = new Task('Setup Grafana', setupPluginRunner); - -/** - * 4. Test (end-to-end) + * 3. Test (end-to-end) * * deploy the zip to a running grafana instance * */ -const testPluginRunner: TaskRunner = async ({ platform }) => { +const testPluginRunner: TaskRunner = async ({ full }) => { const start = Date.now(); const workDir = getJobFolder(); + const pluginInfo = getPluginJson(`${process.cwd()}/src/plugin.json`); const args = { withCredentials: true, @@ -324,10 +310,22 @@ const testPluginRunner: TaskRunner = async ({ platform }) => { console.log('Grafana Version: ' + JSON.stringify(frontendSettings.data.buildInfo, null, 2)); - const pluginInfo = getPluginJson(`${process.cwd()}/src/plugin.json`); - const pluginSettings = await axios.get(`api/plugins/${pluginInfo.id}/settings`, args); - - console.log('Plugin Info: ' + JSON.stringify(pluginSettings.data, null, 2)); + const allPlugins: any[] = await axios.get('api/plugins', args).data; + // for (const plugin of allPlugins) { + // if (plugin.id === pluginInfo.id) { + // console.log('------------'); + // console.log(plugin); + // console.log('------------'); + // } else { + // console.log('Plugin:', plugin.id, plugin.latestVersion); + // } + // } + console.log('PLUGINS:', allPlugins); + + if (full) { + const pluginSettings = await axios.get(`api/plugins/${pluginInfo.id}/settings`, args); + console.log('Plugin Info: ' + JSON.stringify(pluginSettings.data, null, 2)); + } console.log('TODO puppeteer'); @@ -347,33 +345,39 @@ const testPluginRunner: TaskRunner = async ({ platform }) => { export const ciTestPluginTask = new Task('Test Plugin (e2e)', testPluginRunner); /** - * 4. Deploy + * 4. Report * - * deploy the zip to a running grafana instance + * Create a report from all the previous steps * */ -const deployPluginRunner: TaskRunner = async () => { +const pluginReportRunner: TaskRunner = async () => { const start = Date.now(); + const workDir = getJobFolder(); + const reportDir = path.resolve(process.cwd(), 'ci', 'report'); + await execa('rimraf', [reportDir]); + fs.mkdirSync(reportDir); - // TASK Time - if (process.env.CIRCLE_INTERNAL_TASK_DATA) { - const timingInfo = fs.readdirSync(`${process.env.CIRCLE_INTERNAL_TASK_DATA}`); - if (timingInfo) { - timingInfo.forEach(file => { - console.log('TIMING INFO: ', file); - }); + const file = path.resolve(reportDir, `report.txt`); + fs.writeFile(file, `TODO... actually make a report (csv etc)`, err => { + if (err) { + throw new Error('Unable to write: ' + file); } - } + }); - const elapsed = Date.now() - start; - const stats = { - job, - sha1: `${process.env.CIRCLE_SHA1}`, - startTime: start, - buildTime: elapsed, - endTime: Date.now(), - }; - console.log('TODO DEPLOY??', stats); + console.log('TODO... real report'); + writeJobStats(start, workDir); +}; + +export const ciPluginReportTask = new Task('Deploy plugin', pluginReportRunner); + +/** + * 5. Deploy + * + * deploy the zip to a running grafana instance + * + */ +const deployPluginRunner: TaskRunner = async () => { + console.log('TODO DEPLOY??'); console.log(' if PR => write a comment to github with difference '); console.log(' if master | vXYZ ==> upload artifacts to some repo '); }; diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 6b27f4e3bbd94..884f799b5af76 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/ui", - "version": "6.4.0-alpha.2", + "version": "6.4.0-alpha.12", "description": "Grafana Components Library", "keywords": [ "grafana",