diff --git a/.github/actions/test-deploy-to-s3-bucket/action.yml b/.github/actions/test-deploy-to-s3-bucket/action.yml new file mode 100644 index 00000000..ef57a4d9 --- /dev/null +++ b/.github/actions/test-deploy-to-s3-bucket/action.yml @@ -0,0 +1,53 @@ +--- + +name: 'Test deploy-to-s3-bucket action' +description: 'Runs validation agains the deploy-to-s3-bucket action' + +inputs: + aws-account-id: + description: 'The AWS Account id' + required: true + +runs: + using: 'composite' + steps: + - name: 'Install BATS and jq' + shell: bash + run: brew install bats-core jq + + - name: 'Checkout' + uses: actions/checkout@v2 + + - name: 'Use local actions' + uses: ./.github/actions/use-local-actions + + - name: 'Get unique id' + id: id + shell: bash + run: echo "::set-output name=id::$(date '+%s')" + + - name: 'Create archive file' + shell: bash + run: tar -zcvf archive.tgz -C ${{ github.action_path }}/assets . + + - name: 'Run deploy-to-s3-bucket action' + id: unpack + uses: ./actions/deploy-to-s3-bucket + with: + pattern: 'archive.tgz' + s3-bucket: shopsmart-github-actions-tests + s3-bucket-path: ${{ steps.id.outputs.id }} + role-to-assume: arn:aws:iam::${{ inputs.aws-account-id }}:role/github-actions-tests + + - name: 'Configure AWS Credentials' + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-region: 'us-east-1' + role-to-assume: arn:aws:iam::${{ inputs.aws-account-id }}:role/github-actions-tests + + - name: 'Validate' + shell: bash + run: bats -r ${{ github.action_path }}/deploy-to-s3-bucket.bats + env: + S3_BUCKET: shopsmart-github-actions-tests + S3_BUCKET_PATH: ${{ steps.id.outputs.id }} diff --git a/.github/actions/test-deploy-to-s3-bucket/assets b/.github/actions/test-deploy-to-s3-bucket/assets new file mode 120000 index 00000000..a31e363a --- /dev/null +++ b/.github/actions/test-deploy-to-s3-bucket/assets @@ -0,0 +1 @@ +../../../fixtures/assets \ No newline at end of file diff --git a/.github/actions/test-deploy-to-s3-bucket/deploy-to-s3-bucket.bats b/.github/actions/test-deploy-to-s3-bucket/deploy-to-s3-bucket.bats new file mode 100644 index 00000000..785e2265 --- /dev/null +++ b/.github/actions/test-deploy-to-s3-bucket/deploy-to-s3-bucket.bats @@ -0,0 +1,28 @@ +#!/usr/bin/env bats + +function setup() { + : +} + +function teardown() { + : +} + +@test "it should have deployed the assets to the s3 bucket" { + run aws s3 cp --recursive "s3://$S3_BUCKET/$S3_BUCKET_PATH" "$BATS_TEST_TMPDIR" + + [ "$status" -eq 0 ] + [ -f "$BATS_TEST_TMPDIR/index.html" ] + [ -f "$BATS_TEST_TMPDIR/style.css" ] +} + +# @test "it should have set the tag on all assets" { +# run aws s3api get-object-tagging \ +# --bucket $S3_BUCKET \ +# --key $S3_BUCKET_PATH/index.html \ +# --no-cli-pager \ +# | jq -r '.TagSet | to_entries[] | select(.key == "version")' + +# [ "$status" -eq 0 ] +# [ "$output" = "$VERSION" ] +# } diff --git a/.github/actions/test-package-archive/action.yml b/.github/actions/test-package-archive/action.yml new file mode 100644 index 00000000..e7404393 --- /dev/null +++ b/.github/actions/test-package-archive/action.yml @@ -0,0 +1,31 @@ +--- + +name: 'Test package-archive action' +description: 'Runs validation agains the package-archive action' + +runs: + using: 'composite' + steps: + - name: 'Install BATS' + shell: bash + run: brew install bats-core + + - name: 'Checkout' + uses: actions/checkout@v2 + + - name: 'Save off action path' + id: path + shell: bash + run: echo "::set-output name=path::${{ github.action_path }}" + + - name: 'Run package-archive action' + id: unpack + uses: ./actions/package-archive + with: + directory: ${{ github.action_path }}/assets + + - name: 'Validate' + shell: bash + run: bats -r ${{ github.action_path }}/package-archive.bats + env: + FILENAME: ${{ steps.unpack.outputs.filename }} diff --git a/.github/actions/test-package-archive/assets b/.github/actions/test-package-archive/assets new file mode 120000 index 00000000..a31e363a --- /dev/null +++ b/.github/actions/test-package-archive/assets @@ -0,0 +1 @@ +../../../fixtures/assets \ No newline at end of file diff --git a/.github/actions/test-package-archive/package-archive.bats b/.github/actions/test-package-archive/package-archive.bats new file mode 100644 index 00000000..6e2bb2ca --- /dev/null +++ b/.github/actions/test-package-archive/package-archive.bats @@ -0,0 +1,23 @@ +#!/usr/bin/env bats + +function setup() { + : +} + +function teardown() { + : +} + +@test "it should have passed on the filename" { + [ -n "$FILENAME" ] +} + +@test "it should package the archive file" { + [ -f "$FILENAME" ] + + run tar -xf "$FILENAME" -C "$BATS_TEST_TMPDIR" . + + [ "$status" -eq 0 ] + [ -f "$BATS_TEST_TMPDIR/index.html" ] + [ -f "$BATS_TEST_TMPDIR/style.css" ] +} diff --git a/.github/actions/test-setup-node/action.yml b/.github/actions/test-setup-node/action.yml new file mode 100644 index 00000000..dc02de7d --- /dev/null +++ b/.github/actions/test-setup-node/action.yml @@ -0,0 +1,34 @@ +--- + +name: 'Test setup-node' +description: 'Runs validation agains the setup-node action' + +runs: + using: 'composite' + steps: + - name: 'Install BATS' + shell: bash + run: brew install bats-core + + - name: 'Checkout actions' + uses: actions/checkout@v2 + + - name: 'Checkout hello world project' + uses: actions/checkout@v2 + with: + repository: mike-carey/hello-world-nodejs + path: ./hello-world + + - name: 'Run setup-node action' + id: setup + uses: ./actions/setup-node + with: + node-version: '14' + working-directory: ./hello-world + + - name: 'Validate' + shell: bash + run: bats -r ${{ github.action_path }}/setup-node.bats + env: + DIRECTORY: ./hello-world + NODE_VERSION: ${{ steps.setup.outputs.node-version }} diff --git a/.github/actions/test-setup-node/setup-node.bats b/.github/actions/test-setup-node/setup-node.bats new file mode 100644 index 00000000..aba0a64d --- /dev/null +++ b/.github/actions/test-setup-node/setup-node.bats @@ -0,0 +1,21 @@ +#!/usr/bin/env bats + +@test "it should have node installed" { + run node --version + + [ "$status" -eq 0 ] +} + +@test "it should have npm installed" { + run npm --version + + [ "$status" -eq 0 ] +} + +@test "it should have installed node_modules" { + [ -d "$DIRECTORY/node_modules" ] +} + +@test "it should have passed along the node version" { + [ -n "$NODE_VERSION" ] +} diff --git a/.github/actions/test-unpack-archive/action.yml b/.github/actions/test-unpack-archive/action.yml new file mode 100644 index 00000000..891c45cd --- /dev/null +++ b/.github/actions/test-unpack-archive/action.yml @@ -0,0 +1,31 @@ +--- + +name: 'Test unpack-archive action' +description: 'Runs validation agains the unpack-archive action' + +runs: + using: 'composite' + steps: + - name: 'Install BATS' + shell: bash + run: brew install bats-core + + - name: 'Checkout' + uses: actions/checkout@v2 + + - name: 'Create archive file' + shell: bash + run: tar -zcvf archive.tgz -C ${{ github.action_path }}/assets . + + - name: 'Run unpack-archive action' + id: unpack + uses: ./actions/unpack-archive + with: + filename: 'archive.tgz' + + - name: 'Validate' + shell: bash + run: bats -r ${{ github.action_path }}/unpack-archive.bats + env: + DESTINATION: ${{ steps.unpack.outputs.destination }} + MIME_TYPE: ${{ steps.unpack.outputs.mime-type }} diff --git a/.github/actions/test-unpack-archive/assets b/.github/actions/test-unpack-archive/assets new file mode 120000 index 00000000..a31e363a --- /dev/null +++ b/.github/actions/test-unpack-archive/assets @@ -0,0 +1 @@ +../../../fixtures/assets \ No newline at end of file diff --git a/.github/actions/test-unpack-archive/unpack-archive.bats b/.github/actions/test-unpack-archive/unpack-archive.bats new file mode 100644 index 00000000..dab48504 --- /dev/null +++ b/.github/actions/test-unpack-archive/unpack-archive.bats @@ -0,0 +1,14 @@ +#!/usr/bin/env bats + +@test "it should have passed along the destination" { + [ -n "$DESTINATION" ] +} + +@test "it should have passed along the mime type" { + [ -n "$MIME_TYPE" ] +} + +@test "it should have unpacked the archive file" { + [ -f "$DESTINATION/index.html" ] + [ -f "$DESTINATION/style.css" ] +} diff --git a/.github/actions/use-local-actions/action.yml b/.github/actions/use-local-actions/action.yml index 88c0386e..37e31372 100644 --- a/.github/actions/use-local-actions/action.yml +++ b/.github/actions/use-local-actions/action.yml @@ -22,4 +22,4 @@ runs: steps: - name: 'Use local actions' shell: bash - run: $GITHUB_ACTION_PATH/use-local-actions.sh + run: ${{ github.action_path }}/use-local-actions.sh diff --git a/.github/workflows/test-deploy-static-assets.yml b/.github/workflows/test-deploy-static-assets.yml deleted file mode 100644 index 0983187a..00000000 --- a/.github/workflows/test-deploy-static-assets.yml +++ /dev/null @@ -1,43 +0,0 @@ -### -# This test of the action is very limited. If anything, this tests -# that the action is not invalid; however, it does not test any of -# the functionality of downloading release assets or uploading to s3 -# bucket without aws credentials. -## ---- - -name: 'Run deploy-static-assets action' - -on: - pull_request: - paths: - - actions/deploy-static-assets/* - - actions/unpack-archive/* - -defaults: - run: - shell: bash - -jobs: - test-deploy-static-assets-action: - name: 'Uses the deploy-static-assets action' - runs-on: ubuntu-latest - steps: - - name: 'Checkout actions' - uses: actions/checkout@v2 - - - name: 'Use local actions' - uses: ./.github/actions/use-local-actions - - - name: 'Create dummy files' - run: | - mkdir -p static-assets - echo "Hello world" > static-assets/index.html - echo "head p { color: black; }" > static-assets/style.css - tar -zcvf static-assets.tgz -C static-assets/ . - rm -rf static-assets/ - - - name: 'Run deploy static assets' - uses: ./actions/deploy-static-assets - with: - pattern: 'static-assets.tgz' diff --git a/.github/workflows/test-deploy-to-s3-bucket.yml b/.github/workflows/test-deploy-to-s3-bucket.yml new file mode 100644 index 00000000..e316bd1b --- /dev/null +++ b/.github/workflows/test-deploy-to-s3-bucket.yml @@ -0,0 +1,30 @@ +--- + +name: 'Run deploy-to-s3-bucket action' + +on: + pull_request: + paths: + - actions/deploy-to-s3-bucket/* + - actions/unpack-archive/* + +permissions: + id-token: write + contents: read + +defaults: + run: + shell: bash + +jobs: + test-deploy-to-s3-bucket-action: + name: 'Uses the deploy-to-s3-bucket action' + runs-on: ubuntu-latest + steps: + - name: 'Checkout actions' + uses: actions/checkout@v2 + + - name: 'Test deploy-to-s3-bucket action' + uses: ./.github/actions/test-deploy-to-s3-bucket + with: + aws-account-id: ${{ secrets.AWS_ACCOUNT_ID }} diff --git a/.github/workflows/test-npm-run.yml b/.github/workflows/test-npm-run.yml deleted file mode 100644 index 27278a36..00000000 --- a/.github/workflows/test-npm-run.yml +++ /dev/null @@ -1,37 +0,0 @@ ---- - -name: 'Run npm-run action' - -on: - pull_request: - paths: - - actions/npm-setup/* - - actions/npm-run/* - -defaults: - run: - shell: bash - -jobs: - test-npm-run-action: - name: 'Uses the npm-run action' - runs-on: ubuntu-latest - steps: - - name: 'Checkout actions' - uses: actions/checkout@v2 - - - name: 'Use local actions' - uses: ./.github/actions/use-local-actions - - - name: 'Checkout hello world project' - uses: actions/checkout@v2 - with: - repository: mike-carey/hello-world-nodejs - path: ./hello-world - - - name: 'Run npm tests' - uses: ./actions/npm-run - with: - node-version: '14' - working-directory: ./hello-world - command: test diff --git a/.github/workflows/test-npm-setup.yml b/.github/workflows/test-npm-setup.yml deleted file mode 100644 index f2c555f1..00000000 --- a/.github/workflows/test-npm-setup.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- - -name: 'Run npm-setup action' - -on: - pull_request: - paths: - - actions/npm-setup/* - -defaults: - run: - shell: bash - -jobs: - test-npm-run-action: - name: 'Uses the npm-setup action' - runs-on: ubuntu-latest - steps: - - name: 'Checkout actions' - uses: actions/checkout@v2 - - - name: 'Checkout hello world project' - uses: actions/checkout@v2 - with: - repository: mike-carey/hello-world-nodejs - path: ./hello-world - - - name: 'Run npm setup' - uses: ./actions/npm-setup - with: - node-version: '14' - working-directory: ./hello-world - - - name: 'Run npm tests' - working-directory: ./hello-world - run: npm run test diff --git a/.github/workflows/test-package-archive.yml b/.github/workflows/test-package-archive.yml new file mode 100644 index 00000000..fc9eb857 --- /dev/null +++ b/.github/workflows/test-package-archive.yml @@ -0,0 +1,23 @@ +--- + +name: 'Run package-archive action' + +on: + pull_request: + paths: + - actions/package-archive/* + +defaults: + run: + shell: bash + +jobs: + test-package-archive-action: + name: 'Uses the package-archive action' + runs-on: ubuntu-latest + steps: + - name: 'Checkout actions' + uses: actions/checkout@v2 + + - name: 'Test package-archive action' + uses: ./.github/actions/test-package-archive diff --git a/.github/workflows/test-setup-node.yml b/.github/workflows/test-setup-node.yml new file mode 100644 index 00000000..6f77bfe4 --- /dev/null +++ b/.github/workflows/test-setup-node.yml @@ -0,0 +1,24 @@ +--- + +name: 'Run setup-node action' + +on: + pull_request: + paths: + - actions/setup-node/* + - scripts/determine-version.* + +defaults: + run: + shell: bash + +jobs: + test-setup-node-action: + name: 'Uses the setup-node action' + runs-on: ubuntu-latest + steps: + - name: 'Checkout actions' + uses: actions/checkout@v2 + + - name: 'Test setup-node action' + uses: ./.github/actions/test-setup-node diff --git a/.github/workflows/test-unpack-archive.yml b/.github/workflows/test-unpack-archive.yml index 658883ce..28bc0e87 100644 --- a/.github/workflows/test-unpack-archive.yml +++ b/.github/workflows/test-unpack-archive.yml @@ -1,9 +1,3 @@ -### -# This test of the action is very limited. If anything, this tests -# that the action is not invalid; however, it does not test any of -# the functionality of downloading release assets or uploading to s3 -# bucket without aws credentials. -## --- name: 'Run unpack-archive action' @@ -25,15 +19,5 @@ jobs: - name: 'Checkout actions' uses: actions/checkout@v2 - - name: 'Create dummy files' - run: | - mkdir -p static-assets - echo "Hello world" > static-assets/index.html - echo "head p { color: black; }" > static-assets/style.css - tar -zcvf static-assets.tgz -C static-assets/ . - rm -rf static-assets/ - - - name: 'Run unpack archive' - uses: ./actions/unpack-archive - with: - filename: 'static-assets.tgz' + - name: 'Test unpack-archive action' + uses: ./.github/actions/test-unpack-archive diff --git a/actions/deploy-static-assets/static-assets-info.bats b/actions/deploy-static-assets/static-assets-info.bats deleted file mode 100644 index 1f84ee29..00000000 --- a/actions/deploy-static-assets/static-assets-info.bats +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bats - -load static-assets-info.sh - -function setup() { - export AWS_ACCESS_KEY_ID='' - export AWS_SECRET_ACCESS_KEY='' -} - -function teardown() { - : -} - -@test "it should configure aws credentials" { - export AWS_ACCESS_KEY_ID='foo' - export AWS_SECRET_ACCESS_KEY='bar' - - run static-assets-info - - [ "$status" -eq 0 ] - [[ "$output" =~ .*::set-output\ name=configure-aws-credentials::true ]] -} - -@test "it should not configure aws credentials" { - run static-assets-info - - [ "$status" -eq 0 ] - [[ "$output" =~ .*::set-output\ name=configure-aws-credentials::false ]] -} - -@test "it should error because access key id is missing" { - export AWS_SECRET_ACCESS_KEY='bar' - - run static-assets-info - - [ "$status" -ne 0 ] -} - -@test "it should error because secret access key is missing" { - export AWS_ACCESS_KEY_ID='foo' - - run static-assets-info - - [ "$status" -ne 0 ] -} diff --git a/actions/deploy-static-assets/static-assets-info.sh b/actions/deploy-static-assets/static-assets-info.sh deleted file mode 100755 index 5b2a3c55..00000000 --- a/actions/deploy-static-assets/static-assets-info.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -function static-assets-info() { - set -eo pipefail - - # If AWS credentials are provided, we should configure AWS credentials - local configure_aws_credentials="false" - [ -z "$AWS_ACCESS_KEY_ID$AWS_SECRET_ACCESS_KEY" ] || { - configure_aws_credentials="true" - if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then - echo "[ERROR] Either access key id or secret access key has not been provided" >&2 - exit 1 - fi - } - - echo "::set-output name=configure-aws-credentials::$configure_aws_credentials" -} - -if [ "${BASH_SOURCE[0]}" = "$0" ]; then - set -u - - static-assets-info "${@:-}" - exit $? -fi diff --git a/actions/deploy-static-assets/action.yml b/actions/deploy-to-s3-bucket/action.yml similarity index 66% rename from actions/deploy-static-assets/action.yml rename to actions/deploy-to-s3-bucket/action.yml index 29b60fdf..616cfd91 100644 --- a/actions/deploy-static-assets/action.yml +++ b/actions/deploy-to-s3-bucket/action.yml @@ -1,14 +1,13 @@ --- -name: 'Deploy static assets' -description: 'Deploys static assets to an s3 bucket (currently the only supported option)' +name: 'Deploy to s3 bucket' +description: 'Deploys assets to an s3 bucket' inputs: pattern: description: | If downloading release assets from github, the pattern for the assets file. - - Otherwise, the path to the static assets. If it is an archive, it will unpacked. + Otherwise, the path to the assets. If it is an archive, it will unpacked. required: true # GH release Options @@ -39,7 +38,7 @@ inputs: s3-bucket: description: 'The name of the s3 bucket to upload the assets to' - default: '' + required: true s3-bucket-path: description: 'The path within the s3 bucket to upload the assets to' default: '' @@ -56,22 +55,13 @@ inputs: runs: using: 'composite' steps: - - name: 'Get info' - id: info - env: - TAG: ${{ inputs.tag }} - AWS_ACCESS_KEY_ID: ${{ inputs.aws-access-key-id }} - AWS_SECRET_ACCESS_KEY: ${{ inputs.aws-secret-access-key }} - shell: bash - run: ${{ github.action_path }}/static-assets-info.sh "${{ inputs.pattern }}" - - name: 'Install gh cli' shell: bash run: brew install gh # Only if we are downloading assets from gh release if: inputs.tag != '' - - name: 'Download static assets' + - name: 'Download release assets' shell: bash run: gh -R "${{ github.repository }}" release download -p "${{ inputs.pattern }}" "${{ inputs.tag }}" env: @@ -79,12 +69,12 @@ runs: # Only if we are downloading assets from gh release if: inputs.tag != '' - - name: 'Unpack release assets' + - name: 'Unpack assets' id: unpack - uses: shopsmart/github-actions/actions/unpack-archive@v1 + uses: shopsmart/github-actions/actions/unpack-archive@v2 with: filename: ${{ inputs.pattern }} - destination: static-assets + destination: assets - name: 'Configure AWS credentials' uses: aws-actions/configure-aws-credentials@v1 @@ -94,24 +84,19 @@ runs: aws-region: ${{ inputs.aws-region }} role-to-assume: ${{ inputs.role-to-assume }} role-duration-seconds: ${{ inputs.role-duration-seconds }} - # Only if we are using AWS S3 - if: steps.info.outputs.configure-aws-credentials == 'true' - - name: 'Upload static assets' + - name: 'Upload assets' shell: bash - run: $GITHUB_ACTION_PATH/upload-static-assets.sh "${{ steps.unpack.outputs.destination }}" + run: ${{ github.action_path }}/upload-assets.sh "${{ steps.unpack.outputs.destination }}" env: S3_BUCKET: ${{ inputs.s3-bucket }} S3_BUCKET_PATH: ${{ inputs.s3-bucket-path }} - # Only if we are using AWS S3 - if: steps.info.outputs.configure-aws-credentials == 'true' - - name: 'Tag static assets' + - name: 'Tag assets' shell: bash - run: $GITHUB_ACTION_PATH/tag-static-assets.sh "${{ steps.unpack.outputs.destination }}" + run: ${{ github.action_path }}/tag-assets.sh "${{ steps.unpack.outputs.destination }}" env: S3_BUCKET: ${{ inputs.s3-bucket }} S3_BUCKET_PATH: ${{ inputs.s3-bucket-path }} S3_TAGS: ${{ inputs.s3-tags }} - # Only if we are using AWS S3 - if: steps.info.outputs.configure-aws-credentials == 'true' && inputs.s3-tags != '' + if: inputs.s3-tags != '' diff --git a/actions/deploy-static-assets/tag-static-assets.bats b/actions/deploy-to-s3-bucket/tag-assets.bats similarity index 91% rename from actions/deploy-static-assets/tag-static-assets.bats rename to actions/deploy-to-s3-bucket/tag-assets.bats index f634bbad..dfb44a03 100644 --- a/actions/deploy-static-assets/tag-static-assets.bats +++ b/actions/deploy-to-s3-bucket/tag-assets.bats @@ -1,6 +1,6 @@ #!/usr/bin/env bats -load tag-static-assets.sh +load tag-assets.sh function setup() { export AWS_CMD_FILE="$BATS_TEST_TMPDIR/aws.cmd" @@ -31,13 +31,13 @@ function aws() { } @test "it should error out if no path is provided" { - run tag-static-assets + run tag-assets [ "$status" -ne 0 ] } @test "it should tag all assets within path" { - run tag-static-assets "$ASSETS_PATH" + run tag-assets "$ASSETS_PATH" tagset="TagSet=[{Key='Foo',Value='bar'},{Key='team',Value='my-team'},{Key='owner',Value='anonymous'}]" @@ -52,7 +52,7 @@ function aws() { @test "it should tag all assets within path without S3_BUCKET_PATH" { unset S3_BUCKET_PATH - run tag-static-assets "$ASSETS_PATH" + run tag-assets "$ASSETS_PATH" tagset="TagSet=[{Key='Foo',Value='bar'},{Key='team',Value='my-team'},{Key='owner',Value='anonymous'}]" @@ -67,7 +67,7 @@ function aws() { @test "it should do nothing with no tags" { export S3_TAGS='' - run tag-static-assets "$ASSETS_PATH" + run tag-assets "$ASSETS_PATH" [ "$status" -eq 0 ] ! [ -f "$AWS_CMD_FILE" ] diff --git a/actions/deploy-static-assets/tag-static-assets.sh b/actions/deploy-to-s3-bucket/tag-assets.sh similarity index 93% rename from actions/deploy-static-assets/tag-static-assets.sh rename to actions/deploy-to-s3-bucket/tag-assets.sh index 2ecc2ee1..aace83d9 100755 --- a/actions/deploy-static-assets/tag-static-assets.sh +++ b/actions/deploy-to-s3-bucket/tag-assets.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -function tag-static-assets() { +function tag-assets() { set -eo pipefail local path="${1:-}" @@ -40,6 +40,6 @@ function tag-static-assets() { if [ "${BASH_SOURCE[0]}" = "$0" ]; then set -u - tag-static-assets "${@:-}" + tag-assets "${@:-}" exit $? fi diff --git a/actions/deploy-static-assets/upload-static-assets.bats b/actions/deploy-to-s3-bucket/upload-assets.bats similarity index 87% rename from actions/deploy-static-assets/upload-static-assets.bats rename to actions/deploy-to-s3-bucket/upload-assets.bats index 7682ade7..b406bf90 100644 --- a/actions/deploy-static-assets/upload-static-assets.bats +++ b/actions/deploy-to-s3-bucket/upload-assets.bats @@ -1,6 +1,6 @@ #!/usr/bin/env bats -load upload-static-assets.sh +load upload-assets.sh function setup() { export AWS_CMD_FILE="$BATS_TEST_TMPDIR/aws.cmd" @@ -19,7 +19,7 @@ function aws() { } @test "it should copy to s3 bucket without path" { - run upload-static-assets my-path + run upload-assets my-path [ "$status" -eq 0 ] [ -f "$AWS_CMD_FILE" ] @@ -29,7 +29,7 @@ function aws() { @test "it should copy to s3 bucket with path" { export S3_BUCKET_PATH=my-s3-path - run upload-static-assets my-path + run upload-assets my-path [ "$status" -eq 0 ] [ -f "$AWS_CMD_FILE" ] diff --git a/actions/deploy-static-assets/upload-static-assets.sh b/actions/deploy-to-s3-bucket/upload-assets.sh similarity index 82% rename from actions/deploy-static-assets/upload-static-assets.sh rename to actions/deploy-to-s3-bucket/upload-assets.sh index 73382699..ee22706d 100755 --- a/actions/deploy-static-assets/upload-static-assets.sh +++ b/actions/deploy-to-s3-bucket/upload-assets.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -function upload-static-assets() { +function upload-assets() { set -eo pipefail local path="$1" @@ -15,6 +15,6 @@ function upload-static-assets() { if [ "${BASH_SOURCE[0]}" = "$0" ]; then set -u - upload-static-assets "${@:-}" + upload-assets "${@:-}" exit $? fi diff --git a/actions/npm-run/action.yml b/actions/npm-run/action.yml deleted file mode 100644 index e0fe3116..00000000 --- a/actions/npm-run/action.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- - -name: 'Run npm command' -description: 'Runs an npm command' - -inputs: - node-version: - description: 'The node version to use, defaults to the version specified in .nvmrc or .node-version' - default: '' - working-directory: - description: 'The directory to run the setup and command within' - default: '' - command: - description: 'The npm command to run' - required: true - -outputs: - node-version: - description: 'The determined node version' - value: ${{ steps.setup.outputs.node-version }} - stdout: - description: 'Standard out from the npm run command' - value: ${{ steps.run.outputs.stdout }} - stderr: - description: 'Standard error from the npm run command' - value: ${{ steps.run.outputs.stderr }} - -runs: - using: composite - steps: - - - name: 'Setup node' - id: setup - uses: shopsmart/github-actions/actions/npm-setup@v1 - with: - node-version: ${{ inputs.node-version }} - working-directory: ${{ inputs.working-directory }} - - - name: 'Run npm command' - id: run - shell: bash - working-directory: ${{ inputs.working-directory }} - run: $GITHUB_ACTION_PATH/run-npm-command.sh ${{ inputs.command }} diff --git a/actions/npm-run/run-npm-command.bats b/actions/npm-run/run-npm-command.bats deleted file mode 100644 index 7760dda4..00000000 --- a/actions/npm-run/run-npm-command.bats +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bats - -load run-npm-command.sh - -function setup() { - export NPM_CMD_FILE="$BATS_TEST_TMPDIR/npm.cmd" - export -f npm -} - -function teardown() { - rm -f "$NPM_CMD_FILE" - - unset NPM_STATUS -} - -function npm() { - echo "$*" > "$NPM_CMD_FILE" - echo "Stdout -over -multiple -lines" - echo "Stderr -over -multiple -lines" >&2 - - return "${NPM_STATUS:-0}" -} - -@test "it should output stdout and stderr to outputs" { - run run-npm-command - - [ "$status" -eq 0 ] - [[ "$output" =~ .*::set-output\ name=stdout::Stdout'%0A'over'%0A'multiple'%0A'lines.* ]] - [[ "$output" =~ .*::set-output\ name=stderr::Stderr'%0A'over'%0A'multiple'%0A'lines.* ]] -} - -@test "it should error out if the npm command was unsuccessful" { - export NPM_STATUS=255 - - run run-npm-command - - [ $status -eq 255 ] -} diff --git a/actions/npm-run/run-npm-command.sh b/actions/npm-run/run-npm-command.sh deleted file mode 100755 index 415b86a8..00000000 --- a/actions/npm-run/run-npm-command.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -function run-npm-command() { - local args=("$@") - local status=0 - local stdout='' - local stderr='' - - local tmpdir='' - tmpdir="$(mktemp -d)" - # shellcheck disable=SC2064 - # https://github.com/koalaman/shellcheck/wiki/SC2064 - # We want this variable to expand now - trap "rm -rf $tmpdir" EXIT - - local stdout_file="$tmpdir/stdout" - local stderr_file="$tmpdir/stderr" - - echo "[DEBUG] Running npm command: ${args[*]}" >&2 - npm run "${args[@]}" >"$stdout_file" 2>"$stderr_file" - status="$?" - - stdout="$(< "$stdout_file")" - stderr="$(< "$stderr_file")" - - # Multiline outputs need special treatment - # @see https://trstringer.com/github-actions-multiline-strings/ - stdout="${stdout//'%'/'%25'}" - stdout="${stdout//$'\n'/'%0A'}" - stdout="${stdout//$'\r'/'%0D'}" - - stderr="${stderr//'%'/'%25'}" - stderr="${stderr//$'\n'/'%0A'}" - stderr="${stderr//$'\r'/'%0D'}" - - # Outputs - echo "::set-output name=stdout::$stdout" - echo "::set-output name=stderr::$stderr" - - # Return status from npm command - echo "[DEBUG] Status of npm command: $status" >&2 - return "$status" -} - -if [ "${BASH_SOURCE[0]}" = "$0" ]; then - set -u - - run-npm-command "${@:-}" - exit $? -fi diff --git a/actions/npm-setup/determine-node-version.bats b/actions/npm-setup/determine-node-version.bats deleted file mode 100644 index 6a6e3f2a..00000000 --- a/actions/npm-setup/determine-node-version.bats +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bats - -load determine-node-version.sh - -function setup() { - : # Nothing -} - -function teardown() { - unset NODE_VERSION -} - -@test "it should not be able to determine node version" { - pushd "$BATS_TEST_TMPDIR" >/dev/null - run determine-node-version - popd >/dev/null - - [ $status -eq 1 ] -} - -@test "it should use the provided node version" { - pushd "$BATS_TEST_TMPDIR" >/dev/null - export NODE_VERSION=10.x - - run determine-node-version - popd >/dev/null - - [ $status -eq 0 ] - [[ "$output" =~ .*::set-output\ name=node-version::10\.x.* ]] -} - -@test "it should use the node version from .nvmrc" { - pushd "$BATS_TEST_TMPDIR" >/dev/null - echo v10.x > .nvmrc - - run determine-node-version - popd >/dev/null - - [ $status -eq 0 ] - [[ "$output" =~ .*::set-output\ name=node-version::10\.x.* ]] -} - -@test "it should use the node version from .node-version" { - pushd "$BATS_TEST_TMPDIR" >/dev/null - echo 10.x > .node-version - - run determine-node-version - popd >/dev/null - - [ $status -eq 0 ] - [[ "$output" =~ .*::set-output\ name=node-version::10\.x.* ]] -} diff --git a/actions/npm-setup/determine-node-version.sh b/actions/npm-setup/determine-node-version.sh deleted file mode 100755 index cce4ac53..00000000 --- a/actions/npm-setup/determine-node-version.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -function determine-node-version() { - set -eo pipefail - - local node_version="${NODE_VERSION:-}" - if [ -n "$node_version" ]; then - echo "[DEBUG] Node version provided via input: $node_version" >&2 - elif [ -f .nvmrc ]; then - echo "[DEBUG] Found .nvmrc file" >&2 - - node_version="$(< .nvmrc)" - # NVM keeps the v in the version file - node_version="${node_version/v/}" - elif [ -f .node-version ]; then - echo "[DEBUG] Found .node-version file" >&2 - - node_version="$(< .node-version)" - fi - - [ -n "$node_version" ] || { - echo "[ERROR] Could not determine node version" >&2 - return 1 - } - - echo "::set-output name=node-version::$node_version" -} - -if [ "${BASH_SOURCE[0]}" = "$0" ]; then - set -u - - determine-node-version "${@:-}" - exit $? -fi diff --git a/actions/package-archive/action.yml b/actions/package-archive/action.yml new file mode 100644 index 00000000..26331b64 --- /dev/null +++ b/actions/package-archive/action.yml @@ -0,0 +1,33 @@ +--- + +name: 'Package archive' +description: 'Packages a directory into an archive file' + +inputs: + directory: + description: 'The directory where build assets will be output' + required: true + type: + description: 'The archive type to create. Options are tar, tgz, or zip' + default: tgz + extension: + description: 'The extension to use for the file' + default: '' + name: + description: 'The name for the archive; if not provided, it will use the name of the directory' + default: '' + +outputs: + filename: + description: 'The packaged assets file that was uploaded to GH release' + value: ${{ steps.package.outputs.filename }} + +runs: + using: 'composite' + steps: + - name: 'Package archive' + id: package + shell: bash + run: ${{ github.action_path }}/package-archive.sh "${{ inputs.directory }}" "${{ inputs.type }}" "${{ inputs.name }}" + env: + EXTENSION: ${{ inputs.extension }} diff --git a/actions/package-archive/package-archive.bats b/actions/package-archive/package-archive.bats new file mode 100644 index 00000000..7070a76b --- /dev/null +++ b/actions/package-archive/package-archive.bats @@ -0,0 +1,86 @@ +#!/usr/bin/env bats + +load package-archive.sh + +function setup() { + export BUILD_DIRECTORY="$BATS_TEST_TMPDIR/build" + + mkdir -p "$BUILD_DIRECTORY" + + pushd "$BATS_TEST_TMPDIR" >/dev/null + + echo "Hello world" > build/index.html + echo "head p { color: black; }" > build/style.css +} + +function teardown() { + popd >/dev/null + + unset EXTENSION +} + +@test "it should error if build directory does not exist" { + rm -rf "$BUILD_DIRECTORY" + + run package-archive build tgz assets + + [ "$status" -ne 0 ] +} + +@test "it should infer the filename from the build directory" { + run package-archive build + + [ "$status" -eq 0 ] + [ -f "$BATS_TEST_TMPDIR/build.tgz" ] + [[ "$output" =~ .*"::set-output name=filename::build.tgz".* ]] +} + +@test "it should use the EXTENSION environment variable for extension" { + export EXTENSION=tar.gz + + run package-archive build + + [ "$status" -eq 0 ] + [ -f "$BATS_TEST_TMPDIR/build.tar.gz" ] + [[ "$output" =~ .*"::set-output name=filename::build.tar.gz".* ]] +} + +@test "it should package build directory into gzipped tarball" { + run package-archive build tgz assets + + [ "$status" -eq 0 ] + [ -f "$BATS_TEST_TMPDIR/assets.tgz" ] + [[ "$output" =~ .*"::set-output name=filename::assets.tgz".* ]] + + mkdir -p "$BATS_TEST_TMPDIR/unpackaged" + tar -zxf "$BATS_TEST_TMPDIR/assets.tgz" -C "$BATS_TEST_TMPDIR/unpackaged" + [ -f "$BATS_TEST_TMPDIR/unpackaged/index.html" ] + [ -f "$BATS_TEST_TMPDIR/unpackaged/style.css" ] +} + +@test "it should package build directory into tarball" { + run package-archive build tar assets + + [ "$status" -eq 0 ] + [ -f "$BATS_TEST_TMPDIR/assets.tar" ] + [[ "$output" =~ .*"::set-output name=filename::assets.tar".* ]] + + mkdir -p "$BATS_TEST_TMPDIR/unpackaged" + tar -xf "$BATS_TEST_TMPDIR/assets.tar" -C "$BATS_TEST_TMPDIR/unpackaged" + [ -f "$BATS_TEST_TMPDIR/unpackaged/index.html" ] + [ -f "$BATS_TEST_TMPDIR/unpackaged/style.css" ] +} + + +@test "it should package build directory into zip" { + run package-archive build zip assets + + [ "$status" -eq 0 ] + [ -f "$BATS_TEST_TMPDIR/assets.zip" ] + [[ "$output" =~ .*"::set-output name=filename::assets.zip".* ]] + + mkdir -p "$BATS_TEST_TMPDIR/unpackaged" + unzip "$BATS_TEST_TMPDIR/assets.zip" -d "$BATS_TEST_TMPDIR/unpackaged" + [ -f "$BATS_TEST_TMPDIR/unpackaged/index.html" ] + [ -f "$BATS_TEST_TMPDIR/unpackaged/style.css" ] +} diff --git a/actions/package-archive/package-archive.sh b/actions/package-archive/package-archive.sh new file mode 100755 index 00000000..fa095ece --- /dev/null +++ b/actions/package-archive/package-archive.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +function package-archive() { + set -eo pipefail + + local directory="${1:-build}" + local type="${2:-tgz}" + local filename="${3:-}" + local extension="${EXTENSION:-}" + + [ -d "$directory" ] || { + echo "[ERROR] Directory not found: $directory" >&2 + return 1 + } + [ -n "$filename" ] || { + filename="$(basename "$directory")" + echo "[DEBUG] Defaulting the filename from directory to $filename" >&2 + } + + case "$type" in + tar ) + [ -n "$extension" ] || extension=tar + + echo "[INFO ] Packaging up $directory to $filename.$extension into tarball" >&2 + tar -cf "$filename.$extension" -C "$directory" . + ;; + tgz ) + [ -n "$extension" ] || extension=tgz + + echo "[INFO ] Packaging up $directory to $filename.$extension into gzipped tarball" >&2 + tar -zcf "$filename.$extension" -C "$directory" . + ;; + zip ) + [ -n "$extension" ] || extension=zip + + # Save off the working directory because zip has no change directory option + local working_directory="$PWD" + + # Enter the build directory and then zip . + pushd "$directory" >/dev/null || return 3 + echo "[INFO ] Zipping up $directory to $filename.$extension" >&2 + zip -r "$working_directory/$filename.$extension" . + + popd >/dev/null || return 3 + ;; + * ) + echo "[ERROR] Unknown archive type requested: $type" >&2 + return 2 + ;; + esac + + echo "::set-output name=filename::$filename.$extension" +} + +if [ "${BASH_SOURCE[0]}" = "$0" ]; then + set -u + + package-archive "${@:-}" + exit $? +fi diff --git a/actions/npm-setup/action.yml b/actions/setup-node/action.yml similarity index 67% rename from actions/npm-setup/action.yml rename to actions/setup-node/action.yml index 90c8b7ee..03ec5e46 100644 --- a/actions/npm-setup/action.yml +++ b/actions/setup-node/action.yml @@ -9,38 +9,35 @@ inputs: default: '' working-directory: description: 'The directory to run the setup within' - default: '' + default: '.' outputs: node-version: description: 'The determined node version' - value: ${{ steps.version.outputs.node_version }} + value: ${{ steps.version.outputs.version }} runs: using: 'composite' steps: - - - name: 'Determine node version' + - name: 'Determine node version' id: version - run: ${{ github.action_path }}/determine-node-version.sh + run: ${{ github.action_path }}/determine-version.sh node "${{ inputs.node-version }}" shell: bash working-directory: ${{ inputs.working-directory }} - env: - NODE_VERSION: ${{ inputs.node-version }} - - - name: 'Setup node' + + - name: 'Setup node' uses: actions/setup-node@v2 with: - node-version: ${{ steps.version.outputs.node-version }} - - - name: 'Cache npm dependencies' + node-version: ${{ steps.version.outputs.version }} + + - name: 'Cache npm dependencies' uses: actions/cache@v2 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: ${{ runner.os }}-node- - - - name: 'Install npm dependencies' + + - name: 'Install npm dependencies' run: npm ci shell: bash working-directory: ${{ inputs.working-directory }} diff --git a/actions/setup-node/determine-version.sh b/actions/setup-node/determine-version.sh new file mode 120000 index 00000000..44682888 --- /dev/null +++ b/actions/setup-node/determine-version.sh @@ -0,0 +1 @@ +../../scripts/determine-version.sh \ No newline at end of file diff --git a/actions/unpack-archive/action.yml b/actions/unpack-archive/action.yml index f462d46f..9794a9b5 100644 --- a/actions/unpack-archive/action.yml +++ b/actions/unpack-archive/action.yml @@ -25,4 +25,4 @@ runs: - name: 'Unpack archive' id: unpack shell: bash - run: $GITHUB_ACTION_PATH/unpack-archive.sh "${{ inputs.filename }}" "${{ inputs.destination }}" + run: ${{ github.action_path }}/unpack-archive.sh "${{ inputs.filename }}" "${{ inputs.destination }}" diff --git a/fixtures/assets/index.html b/fixtures/assets/index.html new file mode 100644 index 00000000..fd866592 --- /dev/null +++ b/fixtures/assets/index.html @@ -0,0 +1 @@ +Hello world diff --git a/fixtures/assets/style.css b/fixtures/assets/style.css new file mode 100644 index 00000000..c68c1f52 --- /dev/null +++ b/fixtures/assets/style.css @@ -0,0 +1 @@ +head p { color: black; } diff --git a/patterns/node/action.yml b/patterns/node/action.yml new file mode 100644 index 00000000..5d673d79 --- /dev/null +++ b/patterns/node/action.yml @@ -0,0 +1,100 @@ +--- + +name: 'NodeJS Pattern' +description: 'Builds, tests, packages, releases, and/or publishes node applications' + +inputs: + build: + description: 'Indicates to run the build step' + default: 'false' + test: + description: 'Indicates to run the test step' + default: 'false' + release: + description: 'Indicates to upload the build content to a GH release. Requires build and tag.' + default: 'false' + # publish: + # description: 'Indicates to publish the package to NPM' + # default: 'false' + + name: + description: 'The name for the archive; if not provided, it will use the name of the directory' + default: '' + tag: + description: 'The GH release tag to upload the build assets to' + default: '' + working-directory: + description: 'The directory to run steps within' + default: '.' + + build-directory: + description: 'The directory where build output will be output' + default: 'build' + build-env-vars: + description: | + Environment variables to expose when building the node application. Format is one line + per environment variable, $name=$value + + build-env-vars: | + MY_FIRST_VAR=my-value + MY_SECOND_VAR=my-other-value + default: '' + + test-env-vars: + description: | + Environment variables to expose when testing the node application. Format is one line + per environment variable, $name=$value + + test-env-vars: | + MY_FIRST_VAR=my-value + MY_SECOND_VAR=my-other-value + default: '' + +outputs: + node-version: + description: 'The determined node version' + value: ${{ steps.setup.outputs.version }} + filename: + description: 'The packaged assets file that was uploaded to GH release' + value: ${{ steps.package.outputs.filename }} + +runs: + using: 'composite' + steps: + - name: 'Setup node' + id: setup + uses: shopsmart/github-actions/actions/setup-node@v2 + with: + working-directory: ${{ inputs.working-directory }} + + - name: 'Build node application' + shell: bash + run: ${{ github.action_path }}/with-env-vars.sh npm run build + working-directory: ${{ inputs.working-directory }} + env: + ENV_VARS: ${{ inputs.build-env-vars }} + + - name: 'Run tests' + shell: bash + run: ${{ github.action_path }}/with-env-vars.sh npm test + working-directory: ${{ inputs.working-directory }} + env: + ENV_VARS: ${{ inputs.build-env-vars }} + + - name: 'Package build output' + id: package + uses: shopsmart/github-actions/actions/package-archive@v2 + with: + name: ${{ inputs.name }}-${{ inputs.tag }} + directory: ${{ inputs.working-directory }}/${{ inputs.build-directory }} + + - name: 'Upload release assets' + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ inputs.tag }} + files: ${{ steps.package.outputs.filename }} + + # - name: 'Publish to NPM' + # uses: shopsmart/github-actions/actions/publish-to-npm@v2 + # with: + # working-directory: ${{ inputs.working-directory }} diff --git a/patterns/node/with-env-vars.sh b/patterns/node/with-env-vars.sh new file mode 120000 index 00000000..b2e61e08 --- /dev/null +++ b/patterns/node/with-env-vars.sh @@ -0,0 +1 @@ +../../scripts/with-env-vars.sh \ No newline at end of file diff --git a/scripts/determine-version.bats b/scripts/determine-version.bats new file mode 100644 index 00000000..38ec02c5 --- /dev/null +++ b/scripts/determine-version.bats @@ -0,0 +1,36 @@ +#!/usr/bin/env bats + +load determine-version.sh + +function setup() { + pushd "$BATS_TEST_TMPDIR" >/dev/null +} + +function teardown() { + popd >/dev/null +} + +@test "it should determine version from input" { + run determine-version - 1.1.1 + + [ $status -eq 0 ] + [[ "$output" =~ .*::set-output\ name=version::1\.1\.1.* ]] +} + +@test "it should determine version from version file" { + echo 1.1.1 > .node-version + + run determine-version node + + [ $status -eq 0 ] + [[ "$output" =~ .*::set-output\ name=version::1\.1\.1.* ]] +} + +@test "it should determine node version from nvmrc file" { + echo v1.1.1 > .nvmrc + + run determine-version node + + [ $status -eq 0 ] + [[ "$output" =~ .*::set-output\ name=version::1\.1\.1.* ]] +} diff --git a/scripts/determine-version.sh b/scripts/determine-version.sh new file mode 100755 index 00000000..10e433dd --- /dev/null +++ b/scripts/determine-version.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +function determine-version() { + set -eo pipefail + + local type="$1" + local version="${2:-}" + local version_file="${type}-version" + + if [ -n "$version" ]; then + echo "[DEBUG] Found $type version from input: $version" >&2 + elif [ -f "$version_file" ]; then + version="$(< "$version_file")" + echo "[DEBUG] Found $type version from $version_file file: $version" >&2 + else + # Exceptions + case "$type" in + node ) + # Node could be using .nvmrc + if [ -f .nvmrc ]; then + version="$(< .nvmrc)" + # NVM keeps the v in the version file + version="${version/v/}" + echo "[DEBUG] Found $type version from .nvmrc file: $version" >&2 + fi + ;; + esac + fi + + [ -n "$version" ] || { + echo "[ERROR] Could not determine $type version" >&2 + return 1 + } + + echo "::set-output name=version::$version" +} + +if [ "${BASH_SOURCE[0]}" = "$0" ]; then + set -u + + determine-version "${@:-}" + exit $? +fi diff --git a/scripts/with-env-vars.bats b/scripts/with-env-vars.bats new file mode 100644 index 00000000..3bc5a809 --- /dev/null +++ b/scripts/with-env-vars.bats @@ -0,0 +1,26 @@ +#!/usr/bin/env bats + +load with-env-vars.sh + +function setup() { + export -f with-env-vars + + export ENV_VARS='FOO=bar +BAR='\''baz'\'' +BAZ=&this +QUO=;echo \"$USER\" +' +} + +function teardown() { + unset ENV_VARS +} + +@test "it should export environment variables and then exec" { + run with-env-vars sh -c 'echo "FOO=$FOO, BAR=$BAR, BAZ=$BAZ, QUO=$QUO"' + + echo "$output" + + [ "$status" -eq 0 ] + [[ "$output" =~ .*"FOO=bar, BAR=baz, BAZ=&this, QUO=;echo \"\$USER\"".* ]] +} diff --git a/scripts/with-env-vars.sh b/scripts/with-env-vars.sh new file mode 100755 index 00000000..9d2e468a --- /dev/null +++ b/scripts/with-env-vars.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +function with-env-vars() { + set -eo pipefail + + local env_vars="${ENV_VARS:-}" + + local key='' val='' + + [ -z "$env_vars" ] || { + while IFS= read -r env_var; do + # Remove blank space around the string + env_var="$(echo "${env_var?}" | xargs)" + key="${env_var%=*}" + val="${env_var#*=}" + + # Toss out empty lines + [ -n "${env_var?}" ] || continue + + echo "[INFO ] Exporting $key as environment variable" >&2 + export "$key"="${val}" + done <<<"$env_vars" + + echo "[INFO ] Running $*" >&2 + exec "$@" + } +} + +if [ "${BASH_SOURCE[0]}" = "$0" ]; then + set -u + + with-env-vars "${@:-}" + exit $? +fi