From 4a8bd466859aa786d280ea95097561c1ed888df3 Mon Sep 17 00:00:00 2001 From: Travis Jorge Date: Mon, 15 Jun 2026 16:19:57 -0400 Subject: [PATCH] feat: add skip-pull input to reuse a locally present image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an opt-in `skip-pull` input (default 'false', no behavior change when unset) that skips the explicit `docker pull` in the startup step. This lets callers reuse an image already present locally — e.g. one restored from a CI cache via `docker load`, or baked into a self-hosted runner — avoiding a redundant registry round-trip and Docker Hub rate limit usage on every run. It is safe because the pull being skipped is a backgrounded refresh: `localstack start -d` still pulls the image itself if it is genuinely missing, so a caller that sets the flag without a present image is not left without one. The input mirrors the existing `skip-wait` / `skip-startup` convention (kebab-case, string 'false' default) and is threaded root action -> startup sub-action the same way. Includes a CI test job and a README example. --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ README.md | 24 ++++++++++++++++++++++++ action.yml | 7 ++++++- startup/action.yml | 9 ++++++++- 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c6bad6..fee4184 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,36 @@ jobs: LS_VERSION=$(docker ps | grep localstack | cut -d " " -f4 | cut -d ":" -f2) exit $(test "x${LS_VERSION}" = "x3.2.0") + skip-pull-test: + name: 'Test skip-pull uses a locally present image' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Pre-pull the image locally + run: docker pull localstack/localstack-pro:3.2.0 + env: + LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} + + - name: Start LocalStack with skip-pull + uses: jenseng/dynamic-uses@8bc24f0360175e710da532c4d19eafdbed489a06 # v1 + with: + uses: LocalStack/setup-localstack@${{ env.GH_ACTION_VERSION }} + with: |- + { + "image-tag": "3.2.0", + "install-awslocal": "true", + "skip-pull": "true" + } + env: + LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} + GH_ACTION_VERSION: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.ref_name }} + + - name: Assert LocalStack is running from the local image + run: | + LS_VERSION=$(docker ps | grep localstack | cut -d " " -f4 | cut -d ":" -f2) + exit $(test "x${LS_VERSION}" = "x3.2.0") + cloud-pods-save-test: name: 'Test Cloud Pods Action' runs-on: ubuntu-latest diff --git a/README.md b/README.md index 243ef2a..a3e7eb8 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,30 @@ A GitHub Action to setup [LocalStack](https://github.com/localstack/localstack) LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} ``` +### Use a locally cached image (skip the pull) +If you restore the LocalStack image from a CI cache (or bake it into a +self-hosted runner), set `skip-pull: 'true'` to avoid re-pulling it from the +registry. The image must already be present locally — otherwise LocalStack +start will pull it as usual. +```yml +- name: Restore cached LocalStack image + uses: actions/cache@v4 + with: + path: /tmp/localstack-image.tar + key: localstack-pro-3.2.0 + +- name: Load the cached image + run: docker load -i /tmp/localstack-image.tar + +- name: Start LocalStack without pulling + uses: LocalStack/setup-localstack@v0.3.2 + with: + image-tag: '3.2.0' + skip-pull: 'true' + env: + LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} +``` + ### Save a state later on in the pipeline ```yml - name: Save LocalStack State diff --git a/action.yml b/action.yml index edff1c5..47839f9 100644 --- a/action.yml +++ b/action.yml @@ -48,6 +48,10 @@ inputs: description: 'Skip wait for LocalStack' required: false default: 'false' + skip-pull: + description: 'Skip pulling the LocalStack Docker image. Use when the image is already present locally (e.g. restored from a CI cache via `docker load`).' + required: false + default: 'false' skip-ephemeral-stop: description: 'Skip stopping LocalStack Ephemeral Instance' required: false @@ -122,7 +126,8 @@ runs: "use-pro": ${{ toJSON(inputs.use-pro) }}, "configuration": ${{ toJSON(inputs.configuration) }}, "ci-project": ${{ toJSON(inputs.ci-project) }}, - "skip-wait": ${{ toJSON(inputs.skip-wait) }} + "skip-wait": ${{ toJSON(inputs.skip-wait) }}, + "skip-pull": ${{ toJSON(inputs.skip-pull) }} } - name: Create Ephemeral Instance diff --git a/startup/action.yml b/startup/action.yml index 740fccc..c890e2c 100644 --- a/startup/action.yml +++ b/startup/action.yml @@ -26,6 +26,10 @@ inputs: description: 'Skip wait for LocalStack' required: false default: 'false' + skip-pull: + description: 'Skip pulling the LocalStack Docker image. Use when the image is already present locally (e.g. restored from a CI cache via `docker load`). LocalStack start still pulls the image if it is genuinely missing.' + required: false + default: 'false' runs: using: "composite" @@ -75,7 +79,9 @@ runs: fi CONFIGURATION="IMAGE_NAME=${IMAGE_NAME} ${CONFIGURATION}" - docker pull ${IMAGE_NAME} & + if [ "$SKIP_PULL" != "true" ]; then + docker pull ${IMAGE_NAME} & + fi export CI_PROJECT=${{ inputs.ci-project }} eval "${CONFIGURATION} localstack start -d" @@ -90,4 +96,5 @@ runs: USE_PRO: ${{ inputs.use-pro }} CONFIGURATION: ${{ inputs.configuration }} SKIP_WAIT: ${{ inputs.skip-wait }} + SKIP_PULL: ${{ inputs.skip-pull }}