From 4b405a249b3bed4953d1bc4ecb9f21129b550015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20N=C3=A9meth?= Date: Tue, 4 Jun 2024 11:41:49 +0200 Subject: [PATCH] Refactor code (#17) --- .github/workflows/ci.yml | 91 +++++++++++-- .github/workflows/ephemeral.yml | 32 ++++- README.md | 119 +++++++++++++++-- action.yml | 149 ++++++++++++++++------ cloud-pods/action.yml | 2 +- ephemeral/shutdown/action.yml | 6 +- {preview => ephemeral/startup}/action.yml | 25 ++-- finish/action.yml | 6 +- local/action.yml | 46 +++++++ startup/action.yml | 78 +++++++++++ tools/action.yml | 22 ++++ 11 files changed, 490 insertions(+), 86 deletions(-) rename {preview => ephemeral/startup}/action.yml (67%) create mode 100644 local/action.yml create mode 100644 startup/action.yml create mode 100644 tools/action.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cb422c..a850319 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,13 @@ name: LocalStack Test on: push: + paths-ignore: + - ./*.md + - LICENSE pull_request: + paths-ignore: + - ./*.md + - LICENSE workflow_dispatch: schedule: - cron: '48 23 * * 0' @@ -13,17 +19,24 @@ jobs: steps: - uses: actions/checkout@v3 + # We must hack the action call as remote to be able to use the relative paths + # Could it break with different CWD? 🤔 - name: Start LocalStack - uses: ./ + uses: jenseng/dynamic-uses@v1 with: - image-tag: 'latest' - install-awslocal: 'true' - configuration: DEBUG=1 - use-pro: 'true' + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "image-tag": "latest", + "install-awslocal": "true", + "configuration": "DEBUG=1", + "use-pro": "true", + } env: LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + GH_ACTION_VERSION: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} - - name: Run Tests against LocalStack + - name: Run Tests Against LocalStack run: | awslocal s3 mb s3://test awslocal s3 ls @@ -37,13 +50,19 @@ jobs: uses: actions/checkout@v3 - name: Start LocalStack - uses: ./ + uses: jenseng/dynamic-uses@v1 with: - image-tag: 'latest' - install-awslocal: 'true' - use-pro: 'true' + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "image-tag": "latest", + "install-awslocal": "true", + "configuration": "DEBUG=1", + "use-pro": "true", + } env: LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + GH_ACTION_VERSION: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} - name: Run AWS commands run: | @@ -51,9 +70,55 @@ jobs: awslocal sqs create-queue --queue-name test-queue - name: Save the Cloud Pod - uses: LocalStack/setup-localstack/cloud-pods@main + uses: jenseng/dynamic-uses@v1 with: - name: cloud-pods-test - action: save + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "state-name": "cloud-pods-test", + "state-action": "save", + } env: LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + GH_ACTION_VERSION: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} + + local-state-test: + name: 'Test Local State Action' + runs-on: ubuntu-latest + steps: + - name: ⚡️ Checkout the repository + uses: actions/checkout@v3 + + - name: Start LocalStack + uses: jenseng/dynamic-uses@v1 + with: + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "image-tag": "latest", + "install-awslocal": "true", + "configuration": "DEBUG=1", + "use-pro": "true", + } + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + GH_ACTION_VERSION: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} + + - name: Run AWS Commands + run: | + awslocal s3 mb s3://test + awslocal sqs create-queue --queue-name test-queue + + - name: Save the State Artifact + uses: jenseng/dynamic-uses@v1 + with: + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "state-name": "cloud-pods-test", + "state-action": "save", + "state-backend": "local", + } + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + GH_ACTION_VERSION: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} diff --git a/.github/workflows/ephemeral.yml b/.github/workflows/ephemeral.yml index 5feeaa2..cb378fb 100644 --- a/.github/workflows/ephemeral.yml +++ b/.github/workflows/ephemeral.yml @@ -9,14 +9,32 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Deploy Preview - uses: ./preview + - name: Deploy Ephemeral Instance + uses: jenseng/dynamic-uses@v1 with: - localstack-api-key: ${{ secrets.LOCALSTACK_API_KEY }} - github-token: ${{ secrets.GITHUB_TOKEN }} + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "github-token": "${{ secrets.GITHUB_TOKEN }}", + "state-backend": "ephemeral", + "state-action": "start", + "skip-ephemeral-stop": "true" + } + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + GH_ACTION_VERSION: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} + # We want explicit shutdown - name: Shutdown ephemeral instance - uses: ./ephemeral/shutdown + uses: jenseng/dynamic-uses@v1 with: - localstack-api-key: ${{ secrets.LOCALSTACK_API_KEY }} - github-token: ${{ secrets.GITHUB_TOKEN }} + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "github-token": "${{ secrets.GITHUB_TOKEN }}", + "state-backend": "ephemeral", + "state-action": "stop" + } + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + GH_ACTION_VERSION: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} diff --git a/README.md b/README.md index 1d5240f..17fc5be 100644 --- a/README.md +++ b/README.md @@ -8,34 +8,120 @@ A GitHub Action to setup [LocalStack](https://github.com/localstack/localstack) - Pulling a specific version of the LocalStack Docker Image into the GitHub Action runner. - Configuring the [LocalStack CLI](https://docs.localstack.cloud/get-started/#localstack-cli) to launch the Docker container with an optional API token for pro usage. - Installing [LocalStack AWS CLI](https://github.com/localstack/awscli-local), a thin wrapper around the `aws` command line interface for use with LocalStack to run integration tests over AWS services. +- Export/import [LocalStack state](https://docs.localstack.cloud/user-guide/state-management/export-import-state/) as an artifact +- Save/load [LocalStack Cloud Pods](https://docs.localstack.cloud/user-guide/state-management/cloud-pods/) +- Start/stop a [LocalStack Ephemeral Instance](https://docs.localstack.cloud/user-guide/cloud-sandbox/application-previews/) _(EXPERIMENTAL)_ ## Usage -To get started, you can use this minimal example: +### Get started with a minimal example ```yml - name: Start LocalStack - uses: LocalStack/setup-localstack@v0.1.2 + uses: LocalStack/setup-localstack@v0.2.0 with: image-tag: 'latest' install-awslocal: 'true' env: LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} ``` +> **NOTE**: The `LOCALSTACK_API_KEY` environment variable is required to be set if `use-pro` is set to `true`. +If the key is not found LocalStack by default falls back to the CE edition and displays a warning. -### Inputs +### Install only CLIs and startup later +```yml +- name: Install LocalStack CLIs + uses: LocalStack/setup-localstack@v0.2.0 + with: + skip-startup: 'true' + install-awslocal: 'true' + +... + +- name: Start LocalStack + uses: LocalStack/setup-localstack@v0.2.0 + with: + image-tag: 'latest' + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} +``` + +### Save a state later on in the pipeline +```yml +- name: Save LocalStack State + uses: LocalStack/setup-localstack@v0.2.0 + with: + install-awslocal: 'true' + state-backend: cloud-pods + state-action: save + state-name: my-cloud-pod + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} +``` +> **NOTE**: The `LOCALSTACK_API_KEY` environment variable is required to be set to save/load LocalStack's state either as a Cloud Pod or as a file artifact. + +### Load an already saved state +```yml +- name: Start LocalStack and Load State + uses: LocalStack/setup-localstack@v0.2.0 + with: + install-awslocal: 'true' + state-backend: cloud-pods + state-action: load + state-name: my-cloud-pod + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} +``` +> **NOTE**: To load a **local state** from a different GitHub Actions workflow, one must set the `WORKFLOW_ID` environment variable. + +> **NOTE**: The `LOCALSTACK_API_KEY` environment variable is required to be set to **save/load** LocalStack's state either as a Cloud Pod or as a file artifact. + +### Manage App Preview (Ephemeral Instance) +```yml +uses: LocalStack/setup-localstack@$v0.2.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + state-backend: ephemeral + state-action: start + # Adding this option prevents Ephemeral Instance to be stopped after the `preview-cmd` run + skip-ephemeral-stop: 'true' + # Optional script/command to run + preview-cmd: deploy.sh + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + +... + +with: + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + state-backend: ephemeral + state-action: stop + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} +``` + +## Inputs | Input | Description | Default | | ------------------ | -------------------------------------------------------------------------------- | -------- | +| `ci-project` | Name of the CI project to track in LocalStack Cloud | | +| `configuration` | Configuration variables to use while starting LocalStack container | `None` | +| `github-token` | Github token used to create PR comments | | | `image-tag` | Tag of the LocalStack Docker image to use | `latest` | +| `include-preview` | Whether to include the created Ephemeral Instance URL in the PR comment | `false` | | `install-awslocal` | Whether to install the `awslocal` CLI into the build environment | `true` | -| `configuration` | Configuration variables to use while starting LocalStack container | `None` | +| `preview-cmd` | Command(s) used to create a Ephemeral Instance of the PR (can use `$AWS_ENDPOINT_URL`) | | +| `skip-ephemeral-stop` | Skip stopping LocalStack Ephemeral Instance | `false` | +| `skip-startup` | Explicitly prevent LocalStack start up, only installs CLI(s). Recommended to manage state later on in the pipeline or start up an ephemeral instance. | `false` | +| `skip-wait` | Skip waiting for LocalStack to start up | `false` | +| `state-action` | Valid values are `load`, `save`, `start`, `stop`, `` (empty, don't manage state). Values `start`/`stop` only usable with app previews. | `` | +| `state-backend` | Either store the state of LocalStack locally, as a Cloud Pod or start an Ephemeral Instance. Valid values are `cloud-pods`, `ephemeral` or `local`. Use this option in unison with `state-action` to control behaviour. | `cloud-pods` | +| `state-name` | Name of the state artifact (without extension) | `false` | | `use-pro` | Whether to use the Pro version of LocalStack (requires API key to be configured) | `false` | -> **NOTE**: The `LOCALSTACK_API_KEY` environment variable is required to be set if `use-pro` is set to `true`. - -### Example workflow - +## Example workflow ```yml name: LocalStack Test on: [ push, pull_request ] @@ -48,12 +134,15 @@ jobs: - uses: actions/checkout@v3 - name: Start LocalStack - uses: LocalStack/setup-localstack@v0.1.2 + uses: LocalStack/setup-localstack@v0.2.0 with: image-tag: 'latest' install-awslocal: 'true' configuration: DEBUG=1 use-pro: 'true' + state-backend: cloud-pods + state-action: load + state-name: my-cloud-pod env: LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} @@ -61,7 +150,17 @@ jobs: run: | awslocal s3 mb s3://test awslocal s3 ls - echo "Test Execution complete!" + echo "Test Execution complete!" + + - name: Save LocalStack State + uses: LocalStack/setup-localstack@v0.2.0 + with: + state-backend: local + state-action: save + state-name: my-ls-state-artifact + env: + LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }} + WORKFLOW_ID: ${{ env.MY_GOLDEN_LS_STATE }} ``` ## License diff --git a/action.yml b/action.yml index df16a0b..efdea09 100644 --- a/action.yml +++ b/action.yml @@ -32,55 +32,124 @@ inputs: required: false default: '' preview-cmd: - description: 'Command(s) used to create a preview of the PR (can use $AWS_ENDPOINT_URL)' + description: 'Command(s) used to create an Ephemeral Instance of the PR (can use $AWS_ENDPOINT_URL)' + required: false + include-preview: + description: 'Whether to include the created Ephemeral Instance URL in the PR comment' + required: false + skip-startup: + description: | + Explicitly prevent LocalStack start up, only installs CLI(s). + Recommended to manage state later on in the pipeline or start up an ephemeral instance + required: true + default: 'false' + skip-wait: + description: 'Skip wait for LocalStack' + required: false + default: 'false' + skip-ephemeral-stop: + description: 'Skip stopping LocalStack Ephemeral Instance' + required: false + default: 'false' + state-action: + description: | + Manage LocalStack state + Valid values are `load`, `save`, `start`, `stop`, `` (empty, don't manage state) + Values `start`/`stop` only usable with Ephemeral Instances. required: false default: '' + state-backend: + description: | + Either store the state of LocalStack locally, as a cloud pod or start up an ephemeral instance. + Valid values are `cloud-pods`, `ephemeral` or `local`. + Use this option in unison with `state-action` to control behaviour. + required: false + default: 'cloud-pods' + state-name: + description: 'Name of the state artifact (without extension)' + required: false runs: using: "composite" steps: - - name: Initial PR comment - # TODO: potentially replace with Action version number over time - uses: LocalStack/setup-localstack/prepare@main - if: inputs.ci-project && inputs.github-token - with: - github-token: ${{ inputs.github-token }} - ci-project: ${{ inputs.ci-project }} - - - name: Start LocalStack - run: | - pip install pyopenssl -U - - LS_IMAGE_STUB="localstack/localstack" - if [ "x${CODEBUILD_BUILD_ID}" != "x" ]; then - LS_IMAGE_STUB="public.ecr.aws/${LS_IMAGE_STUB}" - fi + - run: echo "$(ls -d ./../../_actions/LocalStack/setup-localstack/* | grep -v completed)" + shell: bash - if [ "$USE_PRO" = true ]; then - docker pull ${LS_IMAGE_STUB}-pro:"$IMAGE_TAG" & - CONFIGURATION="$CONFIGURATION DNS_ADDRESS=127.0.0.1" - else - docker pull ${LS_IMAGE_STUB}:"$IMAGE_TAG" & - fi + - run: echo "GH_ACTION_ROOT=$(ls -d ./../../_actions/LocalStack/setup-localstack/* | grep -v completed)" >> $GITHUB_ENV + shell: bash + + - name: Install tools + uses: jenseng/dynamic-uses@v1 + if: ${{ inputs.skip-startup == 'true' || inputs.state-backend == 'ephemeral' || inputs.state-action == 'save' }} + with: + uses: ${{ env.GH_ACTION_ROOT }}/tools + with: |- + { + "install-awslocal": "${{ inputs.install-awslocal }}", + } - pip install localstack - if [ "$INSTALL_AWSLOCAL" = true ]; then - pip install awscli-local[ver1] - fi + - name: Start Localstack + uses: jenseng/dynamic-uses@v1 + if: ${{ inputs.skip-startup != 'true' && inputs.state-backend != 'ephemeral' && inputs.state-action != 'save' }} + with: + # now we can dynamically determine sub-action path 🥳 + uses: ${{ env.GH_ACTION_ROOT }}/startup + # the `with` needs to be converted to a valid json string + # keeping in there install-awslocal for backward compatibility + with: |- + { + "image-tag": "${{ inputs.image-tag }}", + "install-awslocal": "${{ inputs.install-awslocal }}", + "use-pro": "${{ inputs.use-pro }}", + "configuration": "${{ inputs.configuration }}", + "ci-project": "${{ inputs.ci-project }}", + "skip-wait": "${{ inputs.skip-wait }}" + } - export CI_PROJECT=${{ inputs.ci-project }} - eval "${CONFIGURATION} localstack start -d" + - name: Create Ephemeral Instance + if: ${{ inputs.state-action == 'start' && inputs.state-backend == 'ephemeral' }} + uses: jenseng/dynamic-uses@v1 + with: + uses: ${{ env.GH_ACTION_ROOT }}/ephemeral/startup + with: |- + { + "github-token": "${{ inputs.github-token }}", + "preview-cmd": "${{ inputs.preview-cmd }}", + "auto-load-pod": "${{ inputs.state-name }}" + } - localstack wait -t 30 + # Use different artifact from current workflow's by passing the workflow's id as WORKFLOW_ID env variable + - name: Manage state + if: ${{ inputs.state-action == 'save' || inputs.state-action == 'load' }} + uses: jenseng/dynamic-uses@v1 + with: + uses: ${{ env.GH_ACTION_ROOT }}/${{ inputs.state-backend }} + with: |- + { + "name": "${{ inputs.state-name }}", + "action": "${{ inputs.state-action }}" + } - shell: bash + - name: Display Ephemeral Instance URL + if: ${{ inputs.state-action == 'start' && inputs.state-backend == 'ephemeral' && (inputs.include-preview == 'true' || inputs.ci-project != '') }} + uses: jenseng/dynamic-uses@v1 env: - IMAGE_TAG: "${{ inputs.image-tag }}" - INSTALL_AWSLOCAL: "${{ inputs.install-awslocal }}" - USE_PRO: "${{ inputs.use-pro }}" - CONFIGURATION: "${{ inputs.configuration }}" - - # TODO: potentially add an additional step here to create preview envs, and add a switch to - # enable/disable the "Start LocalStack" action above. This way we could make this action - # the single entry point which then delegates to sub-actions in this repo, based on the - # user-provided configuration... + default-include-preview: ${{ fromJSON('["false","true"]')[github.event_name == 'pull_request'] }} + with: + uses: ${{ env.GH_ACTION_ROOT }}/finish + with: |- + { + "github-token": "${{ inputs.github-token }}", + "ci-project": "${{ inputs.ci-project }}", + "include-preview": "${{ inputs.include-preview != '' && inputs.include-preview || env.include-preview }}" + } + + - name: Stop Ephemeral Instance + if: ${{ !inputs.skip-ephemeral-stop && inputs.state-action == 'stop' && inputs.state-backend == 'ephemeral' }} + uses: jenseng/dynamic-uses@v1 + with: + uses: ${{ env.GH_ACTION_ROOT }}/ephemeral/shutdown + with: |- + { + "name": "${{ inputs.github-token }}", + } \ No newline at end of file diff --git a/cloud-pods/action.yml b/cloud-pods/action.yml index 80dccd6..8058c1c 100644 --- a/cloud-pods/action.yml +++ b/cloud-pods/action.yml @@ -20,7 +20,7 @@ runs: localstack pod save $NAME elif [ "$ACTION" = "load" ]; then echo "Loading Cloud Pod $NAME" - localstack pod load $NAME + localstack pod load --yes $NAME else echo "Invalid action: $ACTION" exit 1 diff --git a/ephemeral/shutdown/action.yml b/ephemeral/shutdown/action.yml index 4e9463c..664e7f7 100644 --- a/ephemeral/shutdown/action.yml +++ b/ephemeral/shutdown/action.yml @@ -30,9 +30,9 @@ runs: previewName=preview-$prId response=$(curl -X DELETE \ - -H 'ls-api-key: ${{ inputs.localstack-api-key }}' \ - -H 'authorization: token ${{ inputs.localstack-api-key }}' \ - -H 'content-type: application/json' \ + -H "ls-api-key: ${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}" \ + -H "authorization: token ${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}" \ + -H "content-type: application/json" \ https://api.localstack.cloud/v1/previews/$previewName) if [[ "$response" != "{}" ]]; then # In case the deletion fails, e.g. if the instance cannot be found, we raise a proper error on the platform diff --git a/preview/action.yml b/ephemeral/startup/action.yml similarity index 67% rename from preview/action.yml rename to ephemeral/startup/action.yml index ad9a604..a3c0981 100644 --- a/preview/action.yml +++ b/ephemeral/startup/action.yml @@ -6,25 +6,31 @@ inputs: required: true localstack-api-key: description: 'LocalStack API key used to create the preview environment' - required: true + required: false preview-cmd: description: 'Command(s) used to create a preview of the PR (can use $AWS_ENDPOINT_URL)' required: false default: '' auto-load-pod: - description: 'The pod to load on startup of localstack, the env var AUTO_LOAD_POD' + description: 'The pod to load on startup of LocalStack, the env var AUTO_LOAD_POD' required: false default: '' runs: using: composite steps: + - run: echo "GH_ACTION_ROOT=$(ls -d ./../../_actions/LocalStack/setup-localstack/* | grep -v completed)" >> $GITHUB_ENV + shell: bash + - name: Initial PR comment - # TODO: potentially replace with Action version number over time - uses: LocalStack/setup-localstack/prepare@main if: inputs.github-token + uses: jenseng/dynamic-uses@v1 with: - github-token: ${{ inputs.github-token }} + uses: ${{ env.GH_ACTION_ROOT }}/prepare + with: |- + { + "github-token": "${{ inputs.github-token }}" + } - name: Download PR artifact uses: actions/download-artifact@v3 @@ -38,10 +44,10 @@ runs: # TODO: make preview name configurable! previewName=preview-$prId - response=$(curl -X POST -d '{"auto_load_pod": "${{ inputs.auto-load-pod }}"}' \ - -H 'ls-api-key: ${{ inputs.localstack-api-key }}' \ - -H 'authorization: token ${{ inputs.localstack-api-key }}' \ - -H 'content-type: application/json' \ + response=$(curl -X POST -d "{\"auto_load_pod\": \"${AUTO_LOAD_POD:-${{ inputs.auto-load-pod }}}\"}" \ + -H "ls-api-key: ${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}" \ + -H "authorization: token ${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}" \ + -H "content-type: application/json" \ https://api.localstack.cloud/v1/previews/$previewName) endpointUrl=$(echo "$response" | jq -r .endpoint_url) if [ "$endpointUrl" = "null" ] || [ "$endpointUrl" = "" ]; then @@ -61,6 +67,7 @@ runs: path: ./ls-preview-url.txt - name: Run preview deployment + if: ${{ inputs.preview-cmd != '' }} shell: bash run: ${{ inputs.preview-cmd }} diff --git a/finish/action.yml b/finish/action.yml index 14b48f6..eb8c95f 100644 --- a/finish/action.yml +++ b/finish/action.yml @@ -8,10 +8,10 @@ inputs: description: 'Name of the CI project tracked in LocalStack Cloud' required: false include-preview: - description: 'Whether to include the created preview URL in the PR comment' + description: 'Whether to include the created Ephemeral Instance URL in the PR comment' required: false preview-url: - description: 'The preview url to include in the PR comment' + description: 'The Ephmeral Instance URL to include in the PR comment' required: false runs: @@ -28,7 +28,7 @@ runs: shell: bash run: echo "pr_id=$(> $GITHUB_OUTPUT - - name: Load the preview URL + - name: Load the Ephemeral Instance URL shell: bash if: inputs.include-preview run: | diff --git a/local/action.yml b/local/action.yml new file mode 100644 index 0000000..9f56139 --- /dev/null +++ b/local/action.yml @@ -0,0 +1,46 @@ +name: 'Save/Load LocalStack state' + +inputs: + name: + description: 'Name of the artifact' + required: true + default: 'ls-state' + action: + description: 'Action to perform (save or load)' + required: true + default: 'save' + +runs: + using: "composite" + steps: + - name: Download PR artifact + uses: dawidd6/action-download-artifact@v2 + if: ${{ inputs.action == 'load' }} + env: + workflow_id: ${{ env.WORKFLOW_ID == '' && github.event.workflow_run.workflow_id || env.WORKFLOW_ID }} + with: + workflow: + name: ${{ inputs.name }} + + - run: | + if [ "$ACTION" = "save" ]; then + echo "Saving State $NAME" + localstack state export ${NAME}.zip + elif [ "$ACTION" = "load" ]; then + echo "Loading State $NAME" + localstack state import ${NAME}.zip + else + echo "Invalid action: $ACTION" + exit 1 + fi + shell: bash + env: + NAME: "${{ inputs.name }}" + ACTION: "${{ inputs.action }}" + + - name: Upload LocalStack State + uses: actions/upload-artifact@v3 + if: ${{ inputs.action == 'save' }} + with: + name: ${{ inputs.name }} + path: ./${{ inputs.name }}.zip diff --git a/startup/action.yml b/startup/action.yml new file mode 100644 index 0000000..bd8b760 --- /dev/null +++ b/startup/action.yml @@ -0,0 +1,78 @@ +name: 'Start up Localstack' + +inputs: + image-tag: + description: 'Tag of the LocalStack Docker image to use' + required: true + default: 'latest' + install-awslocal: + description: 'Whether to install the `awslocal` CLI into the environment' + required: true + default: 'true' + use-pro: + description: 'Whether to use LocalStack Pro (requires a valid API key)' + required: false + default: 'false' + configuration: + description: 'Configuration variables to use for LocalStack' + required: false + default: '' + ci-project: + description: 'Name of the CI project to track in LocalStack Cloud' + required: false + default: '' + skip-wait: + description: 'Skip wait for LocalStack' + required: false + default: 'false' + +runs: + using: "composite" + steps: + # # NOTE: Thinking about this if we need it + # - name: Initial PR comment + # # TODO: potentially replace with Action version number over time + # uses: LocalStack/setup-localstack/prepare@main + # if: inputs.ci-project && inputs.github-token + # with: + # github-token: ${{ inputs.github-token }} + # ci-project: ${{ inputs.ci-project }} + - run: echo "GH_ACTION_ROOT=$(ls -d ./../../_actions/LocalStack/setup-localstack/* | grep -v completed)" >> $GITHUB_ENV + shell: bash + + - name: Install tools + uses: jenseng/dynamic-uses@v1 + with: + uses: ${{ env.GH_ACTION_ROOT }}/tools + with: |- + { + "install-awslocal": "${{ inputs.install-awslocal }}", + } + + - name: Start LocalStack + run: | + if [ "$USE_PRO" = true ]; then + if [ "x$LOCALSTACK_AUTH_TOKEN" = "x" -o "x$LOCALSTACK_API_KEY" = "x" ]; then + echo "WARNING: LocalStack API key not detected, please verify your configuration..." + fi + docker pull localstack/localstack-pro:"$IMAGE_TAG" & + CONFIGURATION="$CONFIGURATION DNS_ADDRESS=127.0.0.1" + else + docker pull localstack/localstack:"$IMAGE_TAG" & + fi + + export CI_PROJECT=${{ inputs.ci-project }} + eval "${CONFIGURATION} localstack start -d" + + if [ "$SKIP_WAIT" = false ]; then + localstack wait -t ${LS_WAIT_TIMEOUT:-30} # Let users configure the timeout via env variable + fi + + shell: bash + env: + IMAGE_TAG: ${{ inputs.image-tag }} + INSTALL_AWSLOCAL: ${{ inputs.install-awslocal }} + USE_PRO: ${{ inputs.use-pro }} + CONFIGURATION: ${{ inputs.configuration }} + SKIP_WAIT: ${{ inputs.skip-wait }} + diff --git a/tools/action.yml b/tools/action.yml new file mode 100644 index 0000000..65b59fd --- /dev/null +++ b/tools/action.yml @@ -0,0 +1,22 @@ +name: 'Install Localstack tools' + +inputs: + install-awslocal: + description: 'Whether to install the `awslocal` CLI into the environment' + required: true + default: 'true' + +runs: + using: "composite" + steps: + - name: Start LocalStack + run: | + which localstack > /dev/null || pip install localstack + if [ "$INSTALL_AWSLOCAL" = true ]; then + which awslocal > /dev/null || pip install awscli-local[ver1] + fi + + shell: bash + env: + INSTALL_AWSLOCAL: "${{ inputs.install-awslocal }}" +