Skip to content

Commit

Permalink
feat(awscli): make awscli internal package into an action as well, ge…
Browse files Browse the repository at this point in the history
…neral purpose use of the awscli
  • Loading branch information
bryantbiggs committed Jan 8, 2020
1 parent 48de053 commit 93de8b7
Show file tree
Hide file tree
Showing 33 changed files with 665 additions and 345 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
**/node_modules

packages/**/dist
packages/**/lib
15 changes: 10 additions & 5 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@
aws-github-actions
</h1>
<p align="center">
<img src="https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg" alt="Maintained with lerna">
<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">
<img src="https://snyk.io/test/github/clowdhaus/aws-github-actions/master/badge.svg" alt="Known Vulnerabilities">
</p>

Collection of GitHub actions for interacting with AWS services.

| Action | Local Action Tests |
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| [CloudFront Invalidate](../packages/cloudfront_invalidate) | ![CloudFront Invalidate](https://github.com/clowdhaus/aws-github-actions/workflows/cloudfront_invalidate/badge.svg) |
| [IAM Access Credentials](../packages/iam_access_credentials) | ![IAM Access Credentials](https://github.com/clowdhaus/aws-github-actions/workflows/iam_access_credentials/badge.svg) |
| [S3 Sync](../packages/s3_sync) | ![S3 Sync](https://github.com/clowdhaus/aws-github-actions/workflows/s3_sync/badge.svg) |
| Action | Local Action Tests |
| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| [`clowdhaus/awscli@master`](../packages/awscli) | ![AWS Command Line Interface](https://github.com/clowdhaus/aws-github-actions/workflows/awscli/badge.svg) |
| [`clowdhaus/cloudfront_invalidate@master`](../packages/cloudfront_invalidate) | ![CloudFront Invalidate](https://github.com/clowdhaus/aws-github-actions/workflows/CloudFront%20Invalidation/badge.svg) |
| [`clowdhaus/iam_access_credentials@master`](../packages/iam_access_credentials) | ![IAM Access Credentials](https://github.com/clowdhaus/aws-github-actions/workflows/IAM%20Credentials/badge.svg) |
| [`clowdhaus/s3_sync@master`](../packages/s3_sync) | ![S3 Sync](https://github.com/clowdhaus/aws-github-actions/workflows/S3%20Sync/badge.svg) |

## Usage

See individual action directory for details on usage and examples.

- [AWS Command Line Interface](../pacakges/awscli) - execute awscli commands
- [CloudFront Invalidate](../packages/cloudfront_invalidate) - invalidate AWS CloudFront distribution to force cache refresh
- [IAM Access Credentials](../packages/iam_access_credentials) - ensure GitHub actions workflow environment has necessary AWS IAM credentials available for subsequent AWS actions
- [S3 Sync](../packages/s3_sync) - synchronize local files to remote AWS S3 bucket
Expand Down
Binary file added .github/images/aws.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions .github/workflows/awscli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: awscli

on:
push:
branches:
- master

jobs:
awscli:
name: Execute some awscli invocations
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Configure AWS Credentials
uses: ./packages/iam_access_credentials
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: List us-east-1 DHCP option set values w/ default json output
uses: ./packages/awscli
with:
cli-command: ec2
cli-subcommand: describe-dhcp-options
cli-parameters: --query DhcpOptions[0].DhcpConfigurations[*].Values[0].Value
aws-region: us-east-1
- name: Get network interface subnet ID
id: net-int-subnet-id
uses: ./packages/awscli
with:
cli-command: ec2
cli-subcommand: describe-network-interfaces
cli-options: --output text
cli-parameters: --query NetworkInterfaces[0].SubnetId
aws-region: us-east-1
- name: Describe interface subnet ID
uses: ./packages/awscli
env:
ACTIONS_RUNNER_DEBUG: true
with:
cli-command: ec2
cli-subcommand: describe-subnets
cli-parameters: --subnet-id ${{ steps.net-int-subnet-id.outputs.cli-output }} --query Subnets[*].Tags
aws-region: us-east-1
7 changes: 5 additions & 2 deletions .github/workflows/cloudfront_invalidate.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: cloudfront_invalidate
name: 'CloudFront Invalidation'

on: [push]
on:
push:
branches:
- master

jobs:
cloudfront-invalidate:
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/iam_access_credentials.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: iam_access_credentials
name: 'IAM Credentials'

on: [push]
on:
push:
branches:
- master

jobs:
s3-sync:
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/s3_sync.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: s3_sync
name: 'S3 Sync'

on: [push]
on:
push:
branches:
- master

jobs:
s3-sync:
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
],
"scripts": {
"test": "lerna run test",
"compile": "lerna run compile",
"compile": "lerna run build && lerna run compile",
"lint": "tsc --noEmit && eslint '*/**/*.{js,ts}' --quiet --fix",
"new-version": "lerna version --conventional-commits --yes",
"diff": "lerna diff",
Expand All @@ -35,17 +35,17 @@
"@actions/core": "^1.2.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^2.14.0",
"@typescript-eslint/parser": "^2.14.0",
"@zeit/ncc": "^0.20.5",
"@typescript-eslint/eslint-plugin": "^2.15.0",
"@typescript-eslint/parser": "^2.15.0",
"@zeit/ncc": "^0.21.0",
"commitizen": "^4.0.3",
"cz-conventional-changelog": "3.0.2",
"cz-conventional-changelog": "^3.0.2",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.9.0",
"eslint-plugin-prettier": "^3.1.2",
"husky": "^3.1.0",
"lerna": "^3.20.1",
"lint-staged": "^10.0.0-beta.14",
"lerna": "^3.20.2",
"lint-staged": "^9.5.0",
"prettier": "^1.19.1",
"typescript": "^3.7.4"
},
Expand Down
92 changes: 92 additions & 0 deletions packages/awscli-core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as process from 'process';

import * as io from '@actions/io';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as tc from '@actions/tool-cache';

export default class AwsCli {
private readonly path: string;

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

public static async getOrInstall(): Promise<AwsCli> {
try {
return await AwsCli.get();
} catch (error) {
core.debug(`Unable to find "awscli" executable, installing it now. Reason: ${error}`);
return await AwsCli.install();
}
}

// Will throw an error if `aws` is not installed.
public static async get(): Promise<AwsCli> {
const exePath = await io.which('aws', true);

return new AwsCli(exePath);
}

private static async install(): Promise<AwsCli> {
switch (process.platform) {
case 'darwin':
case 'linux': {
const AwsCliWheelPath = await tc.downloadTool(
'https://files.pythonhosted.org/packages/99/55/6c020e22f81b2b76a1295b07ac92aa4f9aaf44dcb9cead89a6a24a3d828c/awscli-1.16.309-py2.py3-none-any.whl',
);
await exec.exec('pip', ['install', '--use-wheel', '--no-index', `--find-links=${AwsCliWheelPath}`, 'awscli']);
break;
}

case 'win32': {
const AwsCliMsiPath = await tc.downloadTool('https://s3.amazonaws.com/aws-cli/AWSCLI64PY3.msi');
await exec.exec('msiexec.exe', ['/I', AwsCliMsiPath]);
break;
}

default:
throw new Error(`Unknown platform ${process.platform}, can't install awscli`);
}

// Assuming it is in the $PATH already
return new AwsCli('aws');
}

public async version(): Promise<string> {
const stdout = await this.callStdout(['--version']);

return stdout.split(' ')[1];
}

// awscli which `program`
public async which(program: string): Promise<string> {
const stdout = await this.callStdout(['which', program]);

if (stdout) {
return stdout;
} else {
throw new Error(`Unable to find the ${program}`);
}
}

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

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

await this.call(args, resOptions);

return stdout;
}
}
11 changes: 11 additions & 0 deletions packages/awscli-core/lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default class AwsCli {
private readonly path;
private constructor();
static getOrInstall(): Promise<AwsCli>;
static get(): Promise<AwsCli>;
private static install;
version(): Promise<string>;
which(program: string): Promise<string>;
call(args: string[], options?: {}): Promise<number>;
callStdout(args: string[], options?: {}): Promise<string>;
}
File renamed without changes.
19 changes: 19 additions & 0 deletions packages/awscli-core/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@aws-github-actions/awscli-core",
"version": "0.1.0",
"description": "Wrapper module for awscli",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"dependencies": {
"@actions/exec": "^1.0.2",
"@actions/io": "^1.0.1",
"@actions/tool-cache": "^1.1.2"
},
"devDependencies": {},
"scripts": {
"build": "rm -f lib/* && tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "clowd.haus",
"license": "Apache-2.0"
}
6 changes: 6 additions & 0 deletions packages/awscli-core/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"declaration": true,
"outDir": "lib"
}
}
80 changes: 80 additions & 0 deletions packages/awscli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<p align="center">
<img src="../../.github/images/aws.png" alt="aws" height="128px">
</p>
<h1 style="font-size: 56px; margin: 0; padding: 0;" align="center">
awscli
</h1>
<p align="center">
<img src="https://github.com/clowdhaus/aws-github-actions/workflows/awscli/badge.svg" alt="awscli">
</p>

The `awscli` GitHub action provides access to the official AWS command line interface within an action workflow.

Reference - `aws [options] <command> <subcommand> [parameters]`
Reference - https://docs.aws.amazon.com/cli/latest/reference/index.html#cli-aws

## Usage

```yml
- uses: clowdhaus/awscli@v0.1
with:
# Command passed to awscli, which is infact the service that is the target of
# your invocation <i.e. - ec2, s3, ebs, etc.>
# Required: true
cli-command: ''

# Sub-command passed to awscli, which specifies the command on the target service
# provided in the command <i.e. - for command of ec2, a sub-command could be describe-instances>
# Required: true
cli-subcommand: ''

# CLI Options passed to command invocation
cli-options: ''

# Options passed with command and sub-command to further define invocation
# See `options` under `ec2` (command) `describe-instances (sub-command) here
# for an example of parameters that can be passed
# https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-network-interfaces.html
cli-parameters: ''

# Intended AWS Region the command invocation is executed against
# required: true
aws-region: ''
```

## Scenarios

### Execute describe style command with standard json result output

```yml
- uses: clowdhaus/awscli@v0.1
with:
cli-command: ec2
cli-subcommand: describe-dhcp-options
aws-region: us-east-1
```

### Execute describe style command with query and text output

```yml
- uses: clowdhaus/awscli@v0.1
with:
cli-command: ec2
cli-subcommand: describe-network-interfaces
cli-options: --output text
cli-parameters: --query NetworkInterfaces[0].SubnetId
aws-region: us-east-1
```

### Execute describe style command using output from a prior describe command of ID `net-int-subnet-id`

```yml
- uses: clowdhaus/awscli@v0.1
env:
ACTIONS_RUNNER_DEBUG: true
with:
cli-command: ec2
cli-subcommand: describe-subnets
cli-parameters: --subnet-id ${{ steps.net-int-subnet-id.outputs.cli-output }} --query Subnets[*].Tags
aws-region: us-east-1
```

0 comments on commit 93de8b7

Please sign in to comment.