Skip to content

Commit

Permalink
feat: initial implementation of intalling argocd cli in github action
Browse files Browse the repository at this point in the history
  • Loading branch information
bryantbiggs committed Feb 14, 2021
1 parent 0b8b282 commit 030088d
Show file tree
Hide file tree
Showing 10 changed files with 384 additions and 118 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@
"es6": true,
"jest/globals": true
}
}
}
80 changes: 80 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: integration

on:
pull_request:
branches:
- main
paths:
- 'dist/**'
- 'src/**'
- 'action.yml'
- 'yarn.lock'
push:
branches:
- main
paths:
- 'dist/**'
- 'src/**'
- 'action.yml'
- 'yarn.lock'

jobs:
no-auth:
name: Download w/o auth
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Show version
uses: ./
with:
command: version
options: --client

- name: Check install - should not re-download
uses: ./

with-auth:
name: Download with auth
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Show version
uses: ./
env:
# Only required for first step in workflow where API is called
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
command: version
options: --client

- name: Check install - should not re-download
uses: ./

set-version:
name: Set version
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Show version
uses: ./
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
version: 1.8.0
command: version
options: --client
36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,51 @@
</h1>
<p align="center">
<img src="https://badgen.net/badge/TypeScript/strict%20%F0%9F%92%AA/blue" alt="Strict TypeScript">
<img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly">
<a href="http://commitizen.github.io/cz-cli/" alt="commitizen cli">
<img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly">
</a>
<a href="https://snyk.io/test/github/clowdhaus/argo-cd-action">
<img src="https://snyk.io/test/github/clowdhaus/argo-cd-action/badge.svg" alt="Known Vulnerabilities" data-canonical-src="https://snyk.io/test/github/clowdhaus/argo-cd-action">
</a>
</p>
<p align="center">
<a href="https://github.com/clowdhaus/argo-cd-action/actions?query=workflow%3Atest">
<img src="https://github.com/clowdhaus/argo-cd-action/workflows/test/badge.svg?branch=main" alt="test">
<a href="https://github.com/clowdhaus/argo-cd-action/actions?query=workflow%3Aintegration">
<img src="https://github.com/clowdhaus/argo-cd-action/workflows/integration/badge.svg" alt="integration test">
</a>
</p>

GitHub action for executing Argo CD 🦑

## Usage

See the [ArgoCD CLI documenation](https://argoproj.github.io/argo-cd/user-guide/commands/argocd/) for the list of available commands and options.

```yml
- uses: clowdhaus/argo-cd-action/@main
with:
version: 1.8.4
command: version
options: --client
```
### With GitHub API authentication
If you are running a lot of workflows/jobs quite frequently, you may run into GitHub's API rate limit due to pulling the CLI from the ArgoCD repository. To get around this limitation, add the `GITHUB_TOKEN` as shown below (or see [here](https://github.com/octokit/auth-action.js#createactionauth) for more examples) to utilize a higher rate limit when authenticated.

```yml
TODO
- uses: clowdhaus/argo-cd-action/@main
env:
# Only required for first step in job where API is called
# All subsequent setps in a job will not re-download the CLI
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
command: version
options: --client
- uses: clowdhaus/argo-cd-action/@main
# CLI has already been downloaded in prior step, no call to GitHub API
with:
command: version
options: --client
```

## Getting Started
Expand Down
19 changes: 18 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
name: Argo CD Action
author: Clowd Haus, LLC
description: GitHub action for executing Argo CD
description: GitHub action for installing/executing Argo CD cli
branding:
icon: anchor
color: gray-dark

inputs:
command:
description: >
Command passed to the cli
Reference - https://argoproj.github.io/argo-cd/user-guide/commands/argocd/
required: false
options:
description: >
Command options passed to the cli
Reference - https://argoproj.github.io/argo-cd/user-guide/commands/argocd/
required: false
version:
description: >
Version of Argo CD to install - https://github.com/argoproj/argo-cd/releases
required: false
default: 1.8.4

runs:
using: node12
main: dist/index.js
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@
},
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/io": "^1.0.2",
"node-fetch": "^2.6.1"
"@actions/exec": "^1.0.4",
"@actions/tool-cache": "^1.6.1",
"@octokit/auth-action": "^1.3.2",
"@octokit/rest": "^18.1.0",
"string-argv": "^0.3.1"
},
"devDependencies": {
"@semantic-release/changelog": "^5.0.1",
"@semantic-release/git": "^9.0.0",
"@types/node": "^14.14.25",
"@types/node-fetch": "^2.5.8",
"@types/node": "^14.14.28",
"@typescript-eslint/eslint-plugin": "^4.15.0",
"@typescript-eslint/parser": "^4.15.0",
"@vercel/ncc": "^0.27.0",
Expand All @@ -52,6 +54,10 @@
"semantic-release": "^17.3.8",
"typescript": "^4.1.5"
},
"resolutions": {
"mem": ">=4.0.0",
"yargs-parser": ">=18.1.2"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
Expand Down
103 changes: 103 additions & 0 deletions src/argo-cd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as tc from '@actions/tool-cache';
import * as os from 'os';
import * as path from 'path';
import * as process from 'process';
import {createActionAuth} from '@octokit/auth-action';
import {Octokit} from '@octokit/rest';
import {existsSync, promises as fs} from 'fs';

const PLATFORM = process.platform;
const EXE_NAME = PLATFORM === 'win32' ? 'argocd.exe' : 'argocd';
const ASSET_DEST = path.join(os.homedir(), EXE_NAME);

enum Executable {
aix,
android,
cygwin,
freebsd,
netbsd,
openbsd,
sunos,
darwin = 'argocd-darwin-amd64',
linux = 'argocd-linux-amd64',
win32 = 'argocd-windows-amd64.exe',
}

export default class ArgoCD {
private readonly path: string;

private constructor(exePath: string) {
this.path = exePath;
}

static async getOrDownload(version: string): Promise<ArgoCD> {
if (existsSync(ASSET_DEST)) {
return new ArgoCD(ASSET_DEST);
} else {
core.debug('Unable to find "argocd" executable, downloading it now');
return await ArgoCD.download(version);
}
}

static async getExecutableUrl(version: string): Promise<string> {
// If hitting GitHub API rate limit, add `GITHUB_TOKEN` to raise limit
const octoConfig = process.env.GITHUB_TOKEN ? {authStrategy: createActionAuth} : {};
const octokit = new Octokit(octoConfig);
const executable = Executable[PLATFORM];

try {
const releases = await octokit.repos.getReleaseByTag({
owner: 'argoproj',
repo: 'argo-cd',
tag: `v${version}`,
});

const asset = releases.data.assets.filter((rel: any) => rel.name === executable)[0];
return asset.browser_download_url;
} catch (err) {
core.setFailed(`Action failed with error ${err}`);
return '';
}
}

// download executable for the appropriate platform
static async download(version: string): Promise<ArgoCD> {
const exeutableUrl = await ArgoCD.getExecutableUrl(version);
core.debug(`[debug()] getExecutableUrl: ${exeutableUrl}`);
const assetPath = await tc.downloadTool(exeutableUrl, ASSET_DEST);
core.addPath(assetPath);

if (PLATFORM !== 'win32') {
await fs.chmod(assetPath, 0o755);
}

return new ArgoCD(assetPath);
}

async version(): Promise<string> {
const stdout = await this.callStdout(['version', '--client']);
return stdout.split(' ')[1];
}

async call(args: string[], options?: Record<string, unknown>): Promise<number> {
return await exec.exec(this.path, args, options);
}

// Call the cli and return stdout
async callStdout(args: string[], options?: Record<string, unknown>): Promise<string> {
let stdout = '';
const resOptions = Object.assign({}, options, {
listeners: {
stdout: (buffer: Buffer) => {
stdout += buffer.toString();
},
},
});

await this.call(args, resOptions);

return stdout;
}
}
23 changes: 16 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import * as core from '@actions/core';
import {wait} from './wait';
import stringArgv from 'string-argv';

import ArgoCD from './argo-cd';

async function run(): Promise<void> {
try {
const ms: string = core.getInput('milliseconds');
core.debug(`Waiting ${ms} milliseconds ...`); // debug is only output if you set the secret `ACTIONS_RUNNER_DEBUG` to true
const command = stringArgv(core.getInput('command', {required: false}).trim());
core.debug(`[index] command: ${command}`);
const options = stringArgv(core.getInput('options', {required: false}).trim());
core.debug(`[index] options: ${options}`);
const version = core.getInput('version', {required: false}).trim();
core.debug(`[index] version: ${version}`);

core.debug(new Date().toTimeString());
await wait(parseInt(ms, 10));
core.debug(new Date().toTimeString());
// Get executable
const argocd = await ArgoCD.getOrDownload(version);

core.setOutput('time', new Date().toTimeString());
const args = [...command, ...options];
if (args) {
const result = await argocd.callStdout(args);
core.setOutput('output', result);
}
} catch (error) {
core.setFailed(error.message);
}
Expand Down
9 changes: 0 additions & 9 deletions src/wait.ts

This file was deleted.

Loading

0 comments on commit 030088d

Please sign in to comment.