Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

comma delimited values for parameter overrides and better tagging syntax #54

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/test-action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: action

jobs:
action:
name: Run Unit Tests
runs-on: ubuntu-latest
steps:
- name: echo
run: echo hello world

68 changes: 64 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,67 @@ Deploys AWS CloudFormation Stacks.

The action can be passed a CloudFormation Stack `name` and a `template` file. The `template` file can be a local file existing in the working directory, or a URL to template that exists in an [Amazon S3](https://aws.amazon.com/s3/) bucket. It will create the Stack if it does not exist, or create a [Change Set](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html) to update the Stack. An update fails by default when the Change Set is empty. Setting `no-fail-on-empty-changeset: "1"` will override this behavior and not throw an error.

See [action.yml](action.yml) for the full documentation for this action's inputs and outputs.

> You can learn more about [AWS CloudFormation](https://aws.amazon.com/cloudformation/)


### Inputs

A few inputs are highlighted below. See [action.yml](action.yml) for the full documentation for this action's inputs and outputs.

#### Tags (OPTIONAL)

Key-value pairs to associate with this stack. This input can be in multiple formats. See all examples below.

- YAML Formatted String:
```
- uses: aws-actions/aws-cloudformation-github-deploy@master
with:
name: cloudformation-stack-name
template: https://s3.amazonaws.com/some-template.yaml
tags: |
SystemTag: AWS_CF_GH_DEPLOY
Environment: prod
```

- YAML Formatted String with Key and Value grouping:
```
- uses: aws-actions/aws-cloudformation-github-deploy@master
with:
name: cloudformation-stack-name
template: https://s3.amazonaws.com/some-template.yaml
tags: |
- Key: SystemTag
Value: AWS_CF_GH_DEPLOY
- Key: Environment
Value: prod
```

- JSON Formatted String:
```
- uses: aws-actions/aws-cloudformation-github-deploy@master
with:
name: cloudformation-stack-name
template: https://s3.amazonaws.com/some-template.yaml
tags: |
{
"SystemTag": "AWS_CF_GH_DEPLOY",
"Environment": "prod"
}
```

- JSON Formatted String with Key and Value grouping:
```
- uses: aws-actions/aws-cloudformation-github-deploy@master
with:
name: cloudformation-stack-name
template: https://s3.amazonaws.com/some-template.yaml
tags: |
[
{"Key": "SystemTag", "Value": "AWS_CF_GH_DEPLOY"},
{"Key": "Environment", "Value": "prod"}
]
```

## Credentials and Region

This action relies on the [default behavior of the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html) to determine AWS credentials and region.
Expand Down Expand Up @@ -114,8 +171,8 @@ jobs:
id: eks-cluster
uses: aws-actions/aws-cloudformation-github-deploy@master
with:
name: ${{ steps.env-name.outputs.environment }}-cluster
template: https://s3.amazonaws.com/aws-quickstart/quickstart-amazon-eks/templates/amazon-eks-master.template.yaml
name: cloudformation-stack-name
template: https://s3.amazonaws.com/some-template.yaml
no-fail-on-empty-changeset: "1"
parameter-overrides: >-
AvailabilityZones=${{ github.event.inputs.region }}a,
Expand All @@ -126,6 +183,9 @@ jobs:
EKSPublicAccessEndpoint=Enabled,
EKSPrivateAccessEndpoint=Enabled,
RemoteAccessCIDR=0.0.0.0/0
tags: |
SystemTag: AWS_CF_GH_DEPLOY
Environment: prod

```

Expand Down
4 changes: 4 additions & 0 deletions __tests__/tags1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- Key: key1
Value: val1
- Key: key2
Value: val2
2 changes: 2 additions & 0 deletions __tests__/tags2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
key1: val1
key2: val2
33 changes: 32 additions & 1 deletion __tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { parseTags, isUrl, parseParameters } from '../src/utils'
import * as path from 'path'
import * as fs from 'fs'

jest.mock('@actions/core')

Expand Down Expand Up @@ -31,10 +32,40 @@ describe('Parse Tags', () => {
expect(json).toBeUndefined()
})

test('returns valid Array on valid JSON', async () => {
test('returns valid Array on valid JSON 1', async () => {
const json = parseTags(JSON.stringify([{ Key: 'Test', Value: 'Value' }]))
expect(json).toEqual([{ Key: 'Test', Value: 'Value' }])
})

test('returns valid Array on valid json 2', async () => {
const json = parseTags(JSON.stringify({ key1: 'val1', key2: 'val2' }))
expect(json).toEqual([
{ Key: 'key1', Value: 'val1' },
{ Key: 'key2', Value: 'val2' }
])
})

test('returns valid Array on valid yaml 1', async () => {
const content = fs
.readFileSync(path.join(__dirname, 'tags1.yaml'))
.toString()
const yaml = parseTags(content)
expect(yaml).toEqual([
{ Key: 'key1', Value: 'val1' },
{ Key: 'key2', Value: 'val2' }
])
})

test('returns valid Array on valid yaml 2', async () => {
const content = fs
.readFileSync(path.join(__dirname, 'tags2.yaml'))
.toString()
const yaml = parseTags(content)
expect(yaml).toEqual([
{ Key: 'key1', Value: 'val1' },
{ Key: 'key2', Value: 'val2' }
])
})
})

describe('Parse Parameters', () => {
Expand Down
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ inputs:
required: false
default: "CAPABILITY_IAM"
parameter-overrides:
description: 'The parameters to override in the stack inputs. You can pass a comma-delimited list or a file URL. Comma-delimited list has each entry formatted as <ParameterName>=<ParameterValue>. A JSON file can be a local file with a "file://" prefix or remote URL (e.g. file://file://${{ github.workspace }}/variables.json or http://example.com/variables.json). A local file needs to be specified with an absolute path to it. The file should look like: [ { "ParameterKey": "KeyPairName", "ParameterValue": "MyKey" }]'
description: 'The parameters to override in the stack inputs. You can pass a comma-delimited list or a local JSON file. Comma-delimited list has each entry formatted as <ParameterName>=<ParameterValue>. A local JSON file should be named with "file://" prefix (e.g. file://params.json) and should look like: [ { "ParameterKey": "KeyPairName", "ParameterValue": "MyKey" }]'
required: false
no-execute-changeset:
description: "Indicates whether to execute to the change set or have it reviewed. Default to '0' (will execute the change set)"
Expand Down Expand Up @@ -43,7 +43,7 @@ inputs:
description: "The Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) role that AWS CloudFormation assumes to create the stack. AWS CloudFormation uses the role's credentials to make calls on your behalf. AWS CloudFormation always uses this role for all future operations on the stack. As long as users have permission to operate on the stack, AWS CloudFormation uses this role even if the users don't have permission to pass it. Ensure that the role grants least privilege. If you don't specify a value, AWS CloudFormation uses the role that was previously associated with the stack"
required: false
tags:
description: 'Key-value pairs to associate with this stack. This input should be JSON-formatted, for example [ { "Key": "string", "Value": "string" } ]'
description: 'Key-value pairs to associate with this stack. This input can be in multiple formats. See readme for details.'
required: false
termination-protection:
description: "Whether to enable termination protection on the specified stack. Defaults to '0' (terminated protection will be disabled) This input is only used for stack creation, not for stack update"
Expand Down