mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Toolkit: simplify the plugin ci docker image (#23267)
* removing src dir on publish * Moved from binary to native typescript 1. Moved to a native typescrpt github publish using the existing github client. 2. Change dist.js to detect running in a linked environment. Todo: Optimize docker image for build size. * Optimized build of docker container Much smaller. From 5.47 gb to 2.88 * Feedback from discussion with Ryan - Added gget for getting grafana versions - Added infrastructure for testing - Uploaded new docker image * Fixed typo... Not sure what happened there :) * Added command to download canary * small fix for displaying versions in help * Removed --dev option Should really just rename version to (ex: 1.2.0-dev) * removing src dir on publish * Moved from binary to native typescript 1. Moved to a native typescrpt github publish using the existing github client. 2. Change dist.js to detect running in a linked environment. Todo: Optimize docker image for build size. * Optimized build of docker container Much smaller. From 5.47 gb to 2.88 * Feedback from discussion with Ryan - Added gget for getting grafana versions - Added infrastructure for testing - Uploaded new docker image * Fixed typo... Not sure what happened there :) * Added command to download canary * small fix for displaying versions in help * Removed --dev option Should really just rename version to (ex: 1.2.0-dev)
This commit is contained in:
parent
06ba5201bb
commit
c5252f1b64
@ -34,6 +34,7 @@ export interface PluginMeta<T extends KeyValue = {}> {
|
||||
enabled?: boolean;
|
||||
defaultNavUrl?: string;
|
||||
hasUpdate?: boolean;
|
||||
enterprise?: boolean;
|
||||
latestVersion?: string;
|
||||
pinned?: boolean;
|
||||
}
|
||||
|
@ -1,5 +1,22 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// This bin is used for cli installed from npm
|
||||
const fs = require('fs');
|
||||
|
||||
require('../src/cli/index.js').run();
|
||||
entrypoint = () => {
|
||||
const defaultEntryPoint = '../src/cli/index.js';
|
||||
// We are running in dev mode. Don't use compiled binaries, rather use the dev entrypoint.
|
||||
if (fs.existsSync(`${process.env['HOME']}/.config/yarn/link/@grafana/toolkit`)) {
|
||||
console.log('Running in linked mode');
|
||||
return `${__dirname}/grafana-toolkit.js`;
|
||||
}
|
||||
|
||||
// We are using npx, and a relative path does not find index.js
|
||||
if (!fs.existsSync(defaultEntryPoint) && fs.existsSync(`${__dirname}/../dist/src/cli/index.js`)) {
|
||||
return `${__dirname}/../dist/src/cli/index.js`;
|
||||
}
|
||||
|
||||
// The default entrypoint must exist, return it now.
|
||||
return defaultEntryPoint;
|
||||
};
|
||||
|
||||
require(entrypoint()).run();
|
||||
|
@ -1,51 +1,6 @@
|
||||
FROM circleci/node:12-browsers
|
||||
USER root
|
||||
WORKDIR /tmp
|
||||
|
||||
# Install Go
|
||||
ADD https://dl.google.com/go/go1.14.linux-amd64.tar.gz /tmp
|
||||
RUN echo 08df79b46b0adf498ea9f320a0f23d6ec59e9003660b4c9c1ce8e5e2c6f823ca go1.14.linux-amd64.tar.gz | sha256sum --check --status
|
||||
RUN tar -C /usr/local -xf go1.14.linux-amd64.tar.gz
|
||||
|
||||
# Install golangci-lint
|
||||
ADD https://github.com/golangci/golangci-lint/releases/download/v1.23.7/golangci-lint-1.23.7-linux-amd64.tar.gz /tmp
|
||||
RUN echo 34df1794a2ea8e168b3c98eed3cc0f3e13ed4cba735e4e40ef141df5c41bc086 golangci-lint-1.23.7-linux-amd64.tar.gz | sha256sum --check --status
|
||||
RUN tar xf golangci-lint-1.23.7-linux-amd64.tar.gz
|
||||
RUN mv golangci-lint-1.23.7-linux-amd64/golangci-lint /usr/local/bin
|
||||
RUN ln -s /usr/local/go/bin/go /usr/local/bin/go
|
||||
RUN ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt
|
||||
RUN chmod 755 /usr/local/bin/golangci-lint
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update -y && apt-get install -y adduser libfontconfig1 locate && /bin/rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install code climate
|
||||
ADD https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 /usr/local/bin/cc-test-reporter
|
||||
RUN echo 38f2442892027f61a07f52c845818750261b2ba58bffb043a582495339d37c05 /usr/local/bin/cc-test-reporter | sha256sum --check --status
|
||||
RUN chmod +x /usr/local/bin/cc-test-reporter
|
||||
|
||||
# Download, but don't install previous grafana releases
|
||||
RUN mkdir -pv /usr/local/grafana/deb
|
||||
ADD https://dl.grafana.com/oss/release/grafana_6.6.2_amd64.deb /usr/local/grafana/deb
|
||||
ADD https://dl.grafana.com/oss/release/grafana_6.5.3_amd64.deb /usr/local/grafana/deb
|
||||
ADD https://dl.grafana.com/oss/release/grafana_6.4.5_amd64.deb /usr/local/grafana/deb
|
||||
ADD https://dl.grafana.com/oss/release/grafana_6.3.7_amd64.deb /usr/local/grafana/deb
|
||||
|
||||
# Perform user specific initialization
|
||||
USER circleci
|
||||
RUN mkdir -pv ${HOME}/plugin ${HOME}/go/bin ${HOME}/bin ${HOME}/src ${HOME}/tmp
|
||||
|
||||
# Install grafana release with yarn
|
||||
RUN git clone https://github.com/grafana/grafana.git ${HOME}/src/grafana
|
||||
WORKDIR /home/circleci/src/grafana
|
||||
RUN git checkout tags/v$(curl -s https://raw.githubusercontent.com/grafana/grafana/master/latest.json | jq -r '.stable')
|
||||
RUN yarn cache clean && yarn install --frozen-lockfile
|
||||
|
||||
# Install Mage
|
||||
RUN git clone https://github.com/magefile/mage.git ${HOME}/src/mage
|
||||
WORKDIR /home/circleci/src/mage
|
||||
RUN go run bootstrap.go
|
||||
|
||||
ENV PATH /home/circleci/go/bin:/usr/local/go/bin:/home/circleci/.local/bin:/home/circleci/bin:${PATH}
|
||||
WORKDIR /home/circleci/plugin
|
||||
|
||||
ADD scripts scripts
|
||||
WORKDIR scripts
|
||||
RUN ./deploy.sh
|
||||
ADD install/gget /usr/local/bin/gget
|
||||
|
@ -20,7 +20,7 @@ The home directory will be `/home/circleci`
|
||||
|
||||
All of the above directories are in the path, so there is no need to specify fully qualified paths.
|
||||
|
||||
## Grafana source
|
||||
## Grafana
|
||||
- Installed in `/home/circleci/src/grafana`
|
||||
- `yarn install` has been run
|
||||
|
||||
@ -47,5 +47,15 @@ To test, your CircleCI config will need a run section with something similar to
|
||||
# Building
|
||||
To build, cd to `<srcroot>/packages/grafana-toolkit/docker/grafana-plugin-ci`
|
||||
```
|
||||
docker build .
|
||||
./build.sh
|
||||
```
|
||||
|
||||
# Developing/Testing
|
||||
To test, you should have docker-compose installed.
|
||||
```
|
||||
cd test
|
||||
./start.sh
|
||||
```
|
||||
|
||||
You will be in /home/circleci/test with the buildscripts installed to the local directory.
|
||||
Do your edits/run tests. When saving, your edits will be available in the container immediately.
|
8
packages/grafana-toolkit/docker/grafana-plugin-ci/build.sh
Executable file
8
packages/grafana-toolkit/docker/grafana-plugin-ci/build.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
source ./common.sh
|
||||
|
||||
output=$(docker build . | tee /dev/tty)
|
||||
hash=$(echo "$output" | tail -1 | sed -ne "s/^Successfully built \(.*\)/\1/p")
|
||||
docker tag "$hash" $DOCKER_IMAGE_NAME:latest
|
||||
docker push $DOCKER_IMAGE_NAME:latest
|
||||
|
7
packages/grafana-toolkit/docker/grafana-plugin-ci/common.sh
Executable file
7
packages/grafana-toolkit/docker/grafana-plugin-ci/common.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
##
|
||||
## Common variable declarations
|
||||
##
|
||||
|
||||
DOCKER_IMAGE_NAME="srclosson/grafana-plugin-ci"
|
63
packages/grafana-toolkit/docker/grafana-plugin-ci/install/gget
Executable file
63
packages/grafana-toolkit/docker/grafana-plugin-ci/install/gget
Executable file
@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
##
|
||||
# gget
|
||||
# A script to get and install grafana versions
|
||||
# for usage information see "show_help" below.
|
||||
#
|
||||
|
||||
latest=$(curl -s 'https://raw.githubusercontent.com/grafana/grafana/master/latest.json' | jq -r '.stable')
|
||||
canary=$(curl -s "https://grafana.com/api/grafana/versions" | jq ".items[0].version" | tr -d '"')
|
||||
|
||||
show_help() {
|
||||
echo "Usage: gget <version>"
|
||||
echo ""
|
||||
echo "where <version> can be:"
|
||||
echo " 1) A version from https://grafana.com/grafana/download (ex x.y.z)"
|
||||
echo " 2) latest (currently $latest)"
|
||||
echo " 3) canary (currently $canary)"
|
||||
echo ""
|
||||
echo " -h, --help: Display this help message"
|
||||
echo ""
|
||||
exit 0
|
||||
}
|
||||
|
||||
opts=$(getopt -o h --long help -n 'gget' -- "$@")
|
||||
[ $? -eq 0 ] || {
|
||||
show_help
|
||||
}
|
||||
|
||||
eval set -- "$opts"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
show_help
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
[ -z "$1" ] && show_help
|
||||
|
||||
# Make sure the script is being run as root
|
||||
if [ $EUID -ne 0 ]; then
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
##
|
||||
# MAIN
|
||||
#
|
||||
# Enough setup, let's actually do something
|
||||
#
|
||||
version=$1
|
||||
[ "$version" == "latest" ] && version="$latest"
|
||||
[ "$version" == "canary" ] && version="$canary"
|
||||
wget "https://dl.grafana.com/oss/release/grafana_${version}_amd64.deb" -O "/tmp/grafana_${version}_amd64.deb"
|
||||
dpkg -i "/tmp/grafana_${version}_amd64.deb" && /bin/rm -rfv "/tmp/grafana_${version}_amd64.deb"
|
38
packages/grafana-toolkit/docker/grafana-plugin-ci/scripts/deploy-common.sh
Executable file
38
packages/grafana-toolkit/docker/grafana-plugin-ci/scripts/deploy-common.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
##
|
||||
# Script to deploy a docker image. Must return exit code 0
|
||||
#
|
||||
do_exit() {
|
||||
message="$1"
|
||||
exit_code="$2"
|
||||
|
||||
echo "$message"
|
||||
exit $exit_code
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Get file, get's a file, validates the SHA
|
||||
# @param filename
|
||||
# @param expected sha value
|
||||
# @returns 0 if successful, -1 of checksum validation failed.
|
||||
#
|
||||
get_file () {
|
||||
[ -n "$1" ] && url=$1 || do_exit "url required" -1
|
||||
[ -n "$2" ] && dest=$2 || do_exit "destination required" -2
|
||||
sha=$3
|
||||
file=$(basename $dest)
|
||||
|
||||
wget "$url" -O "$dest"
|
||||
if [ -n "$sha" ]; then
|
||||
echo "$sha $dest" | sha256sum --check --status || do_exit "Checksum validation failed for $file. Exiting" -1
|
||||
fi
|
||||
}
|
||||
|
||||
untar_file () {
|
||||
[ -n "$1" ] && src=$1 || do_exit "src required" -1
|
||||
[ -n "$2" ] && dest=$2 || dest="/usr/local"
|
||||
|
||||
tar -C "$dest" -xf "$src" && /bin/rm -rf "$src"
|
||||
}
|
3
packages/grafana-toolkit/docker/grafana-plugin-ci/scripts/deploy-user.sh
Executable file
3
packages/grafana-toolkit/docker/grafana-plugin-ci/scripts/deploy-user.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
source "./deploy-common.sh"
|
||||
|
43
packages/grafana-toolkit/docker/grafana-plugin-ci/scripts/deploy.sh
Executable file
43
packages/grafana-toolkit/docker/grafana-plugin-ci/scripts/deploy.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
source "./deploy-common.sh"
|
||||
|
||||
# Install Go
|
||||
filename="go1.14.linux-amd64.tar.gz"
|
||||
get_file "https://dl.google.com/go/$filename" "/tmp/$filename" "08df79b46b0adf498ea9f320a0f23d6ec59e9003660b4c9c1ce8e5e2c6f823ca"
|
||||
untar_file "/tmp/$filename"
|
||||
|
||||
|
||||
# Install golangci-lint
|
||||
filename="golangci-lint-1.23.7-linux-amd64.tar.gz"
|
||||
get_file "https://github.com/golangci/golangci-lint/releases/download/v1.23.7/$filename" \
|
||||
"/tmp/$filename" \
|
||||
"34df1794a2ea8e168b3c98eed3cc0f3e13ed4cba735e4e40ef141df5c41bc086"
|
||||
untar_file "/tmp/$filename"
|
||||
chmod 755 /usr/local/bin/golangci-lint
|
||||
ln -s /usr/local/golangci-lint-1.23.7-linux-amd64/golangci-lint /usr/local/bin/golangci-lint
|
||||
ln -s /usr/local/go/bin/go /usr/local/bin/go
|
||||
ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt
|
||||
|
||||
# Install dependencies
|
||||
apt-get update -y && apt-get install -y adduser libfontconfig1 locate && /bin/rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install code climate
|
||||
get_file "https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64" \
|
||||
"/usr/local/bin/cc-test-reporter" \
|
||||
"38f2442892027f61a07f52c845818750261b2ba58bffb043a582495339d37c05"
|
||||
chmod +x /usr/local/bin/cc-test-reporter
|
||||
|
||||
# Install Mage
|
||||
mkdir -pv /tmp/mage $HOME/go/bin
|
||||
git clone https://github.com/magefile/mage.git /tmp/mage
|
||||
pushd /tmp/mage && go run bootstrap.go && popd
|
||||
mv $HOME/go/bin/mage /usr/local/bin
|
||||
# Cleanup after yourself
|
||||
/bin/rm -rf /tmp/mage
|
||||
/bin/rm -rf $HOME/go
|
||||
|
||||
# Perform user specific initialization
|
||||
sudo -u circleci ./deploy-user.sh
|
||||
|
||||
# Get the size down
|
||||
/bin/rm -rf /var/lib/apt/lists
|
@ -0,0 +1,8 @@
|
||||
version: '3'
|
||||
services:
|
||||
citest:
|
||||
image: "circleci/node:12-browsers"
|
||||
user: root
|
||||
volumes:
|
||||
- ../scripts:/home/circleci/scripts
|
||||
- ../install:/home/circleci/install
|
4
packages/grafana-toolkit/docker/grafana-plugin-ci/test/start.sh
Executable file
4
packages/grafana-toolkit/docker/grafana-plugin-ci/test/start.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Enter the docker container
|
||||
docker-compose run citest bash -c "cd /home/circleci; exec bash --login -i"
|
@ -200,14 +200,12 @@ export const run = (includeInternalScripts = false) => {
|
||||
.option('--dryrun', 'Do a dry run only', false)
|
||||
.option('--verbose', 'Print verbose', false)
|
||||
.option('--commitHash <hashKey>', 'Specify the commit hash')
|
||||
.option('--recreate', 'Recreate the release if already present')
|
||||
.description('Publish to github ... etc etc etc')
|
||||
.description('Publish to github')
|
||||
.action(async cmd => {
|
||||
await execTask(githubPublishTask)({
|
||||
dryrun: cmd.dryrun,
|
||||
verbose: cmd.verbose,
|
||||
commitHash: cmd.commitHash,
|
||||
recreate: cmd.recreate,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -4,7 +4,6 @@ import { GitHubRelease } from '../utils/githubRelease';
|
||||
import { getPluginId } from '../../config/utils/getPluginId';
|
||||
import { getCiFolder } from '../../plugins/env';
|
||||
import { useSpinner } from '../utils/useSpinner';
|
||||
|
||||
import path = require('path');
|
||||
|
||||
// @ts-ignore
|
||||
@ -20,10 +19,11 @@ const releaseNotes = async (): Promise<string> => {
|
||||
const checkoutBranch = async (branchName: string): Promise<Command> => {
|
||||
const currentBranch = await execa.shell(`git rev-parse --abbrev-ref HEAD`);
|
||||
const branchesAvailable = await execa.shell(
|
||||
`(git branch -a | grep ${branchName} | grep -v remote) || echo 'No release found'`
|
||||
`(git branch -a | grep "${branchName}$" | grep -v remote) || echo 'No release found'`
|
||||
);
|
||||
|
||||
if (currentBranch.stdout !== branchName) {
|
||||
console.log('available', branchesAvailable.stdout.trim());
|
||||
if (branchesAvailable.stdout.trim() === branchName) {
|
||||
return ['git', ['checkout', branchName]];
|
||||
} else {
|
||||
@ -61,27 +61,28 @@ const prepareRelease = useSpinner<any>('Preparing release', async ({ dryrun, ver
|
||||
const distDir = path.resolve(ciDir, 'dist');
|
||||
const distContentDir = path.resolve(distDir, getPluginId());
|
||||
const pluginJsonFile = path.resolve(distContentDir, 'plugin.json');
|
||||
const pluginVersion = getPluginJson(pluginJsonFile).info.version;
|
||||
const pluginJson = getPluginJson(pluginJsonFile);
|
||||
const GIT_EMAIL = 'eng@grafana.com';
|
||||
const GIT_USERNAME = 'CircleCI Automation';
|
||||
|
||||
const githubPublishScript: Command = [
|
||||
['git', ['config', 'user.email', GIT_EMAIL]],
|
||||
['git', ['config', 'user.name', GIT_USERNAME]],
|
||||
await checkoutBranch(`release-${pluginVersion}`),
|
||||
['cp', ['-rf', distContentDir, 'dist'], { dryrun }],
|
||||
await checkoutBranch(`release-${pluginJson.info.version}`),
|
||||
['cp', ['-rf', distContentDir, 'dist']],
|
||||
['git', ['add', '--force', distDir], { dryrun }],
|
||||
['git', ['add', '--force', 'dist'], { dryrun }],
|
||||
['/bin/rm', ['-rf', 'src'], { enterprise: true }],
|
||||
[
|
||||
'git',
|
||||
['commit', '-m', `automated release ${pluginVersion} [skip ci]`],
|
||||
['commit', '-m', `automated release ${pluginJson.info.version} [skip ci]`],
|
||||
{
|
||||
dryrun,
|
||||
okOnError: [/nothing to commit/g, /nothing added to commit/g, /no changes added to commit/g],
|
||||
},
|
||||
],
|
||||
['git', ['tag', '-f', pluginVersion]],
|
||||
['git', ['push', '-f', 'origin', `release-${pluginVersion}`], { dryrun }],
|
||||
['git', ['tag', '-f', pluginJson.info.version]],
|
||||
['git', ['push', '-f', 'origin', `release-${pluginJson.info.version}`], { dryrun }],
|
||||
];
|
||||
|
||||
for (let line of githubPublishScript) {
|
||||
@ -98,6 +99,11 @@ const prepareRelease = useSpinner<any>('Preparing release', async ({ dryrun, ver
|
||||
if (opts['dryrun']) {
|
||||
line[1].push('--dry-run');
|
||||
}
|
||||
|
||||
if (pluginJson.enterprise && !opts['enterprise']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { stdout } = await execa(command, args);
|
||||
if (verbose) {
|
||||
console.log(stdout);
|
||||
@ -129,19 +135,18 @@ const prepareRelease = useSpinner<any>('Preparing release', async ({ dryrun, ver
|
||||
}
|
||||
});
|
||||
|
||||
interface GithubPluglishReleaseOptions {
|
||||
interface GithubPublishReleaseOptions {
|
||||
commitHash?: string;
|
||||
recreate?: boolean;
|
||||
githubToken: string;
|
||||
gitRepoOwner: string;
|
||||
gitRepoName: string;
|
||||
}
|
||||
|
||||
const createRelease = useSpinner<GithubPluglishReleaseOptions>(
|
||||
const createRelease = useSpinner<GithubPublishReleaseOptions>(
|
||||
'Creating release',
|
||||
async ({ commitHash, recreate, githubToken, gitRepoName, gitRepoOwner }) => {
|
||||
async ({ commitHash, githubToken, gitRepoName, gitRepoOwner }) => {
|
||||
const gitRelease = new GitHubRelease(githubToken, gitRepoOwner, gitRepoName, await releaseNotes(), commitHash);
|
||||
return gitRelease.release(recreate || false);
|
||||
return gitRelease.release();
|
||||
}
|
||||
);
|
||||
|
||||
@ -149,10 +154,10 @@ export interface GithubPublishOptions {
|
||||
dryrun?: boolean;
|
||||
verbose?: boolean;
|
||||
commitHash?: string;
|
||||
recreate?: boolean;
|
||||
dev?: boolean;
|
||||
}
|
||||
|
||||
const githubPublishRunner: TaskRunner<GithubPublishOptions> = async ({ dryrun, verbose, commitHash, recreate }) => {
|
||||
const githubPublishRunner: TaskRunner<GithubPublishOptions> = async ({ dryrun, verbose, commitHash }) => {
|
||||
if (!process.env['CIRCLE_REPOSITORY_URL']) {
|
||||
throw `The release plugin requires you specify the repository url as environment variable CIRCLE_REPOSITORY_URL`;
|
||||
}
|
||||
@ -172,7 +177,6 @@ const githubPublishRunner: TaskRunner<GithubPublishOptions> = async ({ dryrun, v
|
||||
|
||||
await createRelease({
|
||||
commitHash,
|
||||
recreate,
|
||||
githubToken,
|
||||
gitRepoOwner: parsedUrl.owner,
|
||||
gitRepoName: parsedUrl.name,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||
|
||||
const grafanaURL = 'https://api.github.com/repos/grafana/grafana';
|
||||
const grafanaURL = (repo: string) => `https://api.github.com/repos/grafana/${repo}`;
|
||||
const enterpriseURL = 'https://api.github.com/repos/grafana/grafana-enterprise';
|
||||
|
||||
// Encapsulates the creation of a client for the Github API
|
||||
@ -14,17 +14,18 @@ const enterpriseURL = 'https://api.github.com/repos/grafana/grafana-enterprise';
|
||||
interface GithubClientProps {
|
||||
required?: boolean;
|
||||
enterprise?: boolean;
|
||||
repo?: string;
|
||||
}
|
||||
|
||||
class GithubClient {
|
||||
client: AxiosInstance;
|
||||
|
||||
constructor({ required = false, enterprise = false }: GithubClientProps = {}) {
|
||||
constructor({ required = false, enterprise = false, repo = 'grafana' }: GithubClientProps = {}) {
|
||||
const username = process.env.GITHUB_USERNAME;
|
||||
const token = process.env.GITHUB_ACCESS_TOKEN;
|
||||
|
||||
const clientConfig: AxiosRequestConfig = {
|
||||
baseURL: enterprise ? enterpriseURL : grafanaURL,
|
||||
baseURL: enterprise ? enterpriseURL : grafanaURL(repo),
|
||||
timeout: 10000,
|
||||
};
|
||||
|
||||
|
@ -2,19 +2,22 @@ import { getPluginId } from '../../config/utils/getPluginId';
|
||||
import { getPluginJson } from '../../config/utils/pluginValidation';
|
||||
import { getCiFolder } from '../../plugins/env';
|
||||
import path = require('path');
|
||||
import fs = require('fs');
|
||||
// @ts-ignore
|
||||
import execa = require('execa');
|
||||
// import execa = require('execa');
|
||||
import GithubClient from './githubClient';
|
||||
import { AxiosResponse } from 'axios';
|
||||
|
||||
const ghrPlatform = (): string => {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
return 'windows';
|
||||
case 'darwin':
|
||||
return 'darwin';
|
||||
case 'linux':
|
||||
return 'linux';
|
||||
const resolveContentType = (extension: string): string => {
|
||||
switch (extension) {
|
||||
case 'zip':
|
||||
return 'application/zip';
|
||||
case 'json':
|
||||
return 'application/json';
|
||||
case 'sha1':
|
||||
return 'text/plain';
|
||||
default:
|
||||
return process.platform;
|
||||
return 'application/octet-stream';
|
||||
}
|
||||
};
|
||||
|
||||
@ -24,6 +27,7 @@ class GitHubRelease {
|
||||
repository: string;
|
||||
releaseNotes: string;
|
||||
commitHash?: string;
|
||||
git: GithubClient;
|
||||
|
||||
constructor(token: string, username: string, repository: string, releaseNotes: string, commitHash?: string) {
|
||||
this.token = token;
|
||||
@ -31,36 +35,37 @@ class GitHubRelease {
|
||||
this.repository = repository;
|
||||
this.releaseNotes = releaseNotes;
|
||||
this.commitHash = commitHash;
|
||||
|
||||
this.git = new GithubClient({
|
||||
repo: repository,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ghr binary to perform the release
|
||||
*/
|
||||
private async getGhr(): Promise<string> {
|
||||
const GHR_VERSION = '0.13.0';
|
||||
const GHR_ARCH = process.arch === 'x64' ? 'amd64' : '386';
|
||||
const GHR_PLATFORM = ghrPlatform();
|
||||
const GHR_EXTENSION = process.platform === 'linux' ? 'tar.gz' : 'zip';
|
||||
const outName = `./ghr.${GHR_EXTENSION}`;
|
||||
const archiveName = `ghr_v${GHR_VERSION}_${GHR_PLATFORM}_${GHR_ARCH}`;
|
||||
const exeName = process.platform === 'linux' ? 'ghr' : 'ghr.exe';
|
||||
const exeNameFullPath = path.resolve(process.cwd(), archiveName, exeName);
|
||||
const ghrUrl = `https://github.com/tcnksm/ghr/releases/download/v${GHR_VERSION}/${archiveName}.${GHR_EXTENSION}`;
|
||||
await execa('wget', [ghrUrl, `--output-document=${outName}`]);
|
||||
if (GHR_EXTENSION === 'tar.gz') {
|
||||
await execa('tar', ['zxvf', outName]);
|
||||
} else {
|
||||
await execa('unzip', ['-p', outName]);
|
||||
}
|
||||
async publishAssets(srcLocation: string, destUrl: string) {
|
||||
// Add the assets. Loop through files in the ci/dist folder and upload each asset.
|
||||
fs.readdir(srcLocation, (err: NodeJS.ErrnoException | null, files: string[]) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
await execa('chmod', ['755', exeNameFullPath]);
|
||||
}
|
||||
|
||||
return exeNameFullPath;
|
||||
files.forEach(async (file: string) => {
|
||||
const fileStat = fs.statSync(`${srcLocation}/${file}`);
|
||||
const fileData = fs.readFileSync(`${srcLocation}/${file}`);
|
||||
try {
|
||||
await this.git.client.post(`${destUrl}?name=${file}`, fileData, {
|
||||
headers: {
|
||||
'Content-Type': resolveContentType(path.extname(file)),
|
||||
'Content-Length': fileStat.size,
|
||||
},
|
||||
});
|
||||
} catch (reason) {
|
||||
console.log('Could not post', reason);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async release(recreate: boolean) {
|
||||
async release() {
|
||||
const ciDir = getCiFolder();
|
||||
const distDir = path.resolve(ciDir, 'dist');
|
||||
const distContentDir = path.resolve(distDir, getPluginId());
|
||||
@ -69,37 +74,31 @@ class GitHubRelease {
|
||||
const PUBLISH_DIR = path.resolve(getCiFolder(), 'packages');
|
||||
const commitHash = this.commitHash || pluginInfo.build?.hash;
|
||||
|
||||
// Get the ghr binary according to platform
|
||||
const ghrExe = await this.getGhr();
|
||||
try {
|
||||
const latestRelease: AxiosResponse<any> = await this.git.client.get('releases/latest');
|
||||
|
||||
if (!commitHash) {
|
||||
throw 'The release plugin was not able to locate a commithash for release. Either build using the ci, or specify the commit hash with --commitHash <value>';
|
||||
// Re-release if the version is the same as an existing release
|
||||
if (latestRelease.data.tag_name === `v${pluginInfo.version}`) {
|
||||
await this.git.client.delete(`releases/${latestRelease.data.id}`);
|
||||
}
|
||||
|
||||
// Now make the release
|
||||
const newReleaseResponse = await this.git.client.post('releases', {
|
||||
tag_name: `v${pluginInfo.version}`,
|
||||
target_commitish: commitHash,
|
||||
name: `v${pluginInfo.version}`,
|
||||
body: this.releaseNotes,
|
||||
draft: false,
|
||||
prerelease: false,
|
||||
});
|
||||
|
||||
this.publishAssets(
|
||||
PUBLISH_DIR,
|
||||
`https://uploads.github.com/repos/${this.username}/${this.repository}/releases/${newReleaseResponse.data.id}/assets`
|
||||
);
|
||||
} catch (reason) {
|
||||
console.error('error', reason);
|
||||
}
|
||||
|
||||
const args = [
|
||||
'-t',
|
||||
this.token,
|
||||
'-u',
|
||||
this.username,
|
||||
'-r',
|
||||
this.repository, // should override --- may not be the same
|
||||
'-c',
|
||||
commitHash,
|
||||
'-n',
|
||||
`${this.repository}_v${pluginInfo.version}`,
|
||||
'-b',
|
||||
this.releaseNotes,
|
||||
`v${pluginInfo.version}`,
|
||||
PUBLISH_DIR,
|
||||
];
|
||||
|
||||
if (recreate) {
|
||||
args.splice(12, 0, '-recreate');
|
||||
}
|
||||
|
||||
const { stdout } = await execa(ghrExe, args);
|
||||
|
||||
console.log(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user