Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions .github/workflows/baseshift.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
name: LocalStack Baseshift Extension Tests

on:
schedule:
- cron: '0 2 * * 1-5'
pull_request:
branches:
- main
paths:
- .github/workflows/baseshift.yml
- 'baseshift/**'
push:
branches:
- main
paths:
- .github/workflows/baseshift.yml
- 'baseshift/**'
workflow_dispatch:

env:
LOCALSTACK_DISABLE_EVENTS: "1"
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}

jobs:
integration-tests:
name: Run Baseshift Extension Tests (${{ matrix.emulator }}, ${{ matrix.tag }})
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
# the Snowflake emulator image also provides the AWS services, and is used for the end-to-end demo
emulator:
- aws
- snowflake
tag:
- latest
- dev
env:
LOCALSTACK_EMULATOR: ${{ matrix.emulator }}
LOCALSTACK_TAG: ${{ matrix.tag }}
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Install lstk CLI
# version is pinned; there is no lockfile for global CLI tools
run: | # zizmor: ignore[adhoc-packages]
npm install -g @localstack/lstk@1.2.0
lstk --version

- name: Build extension
run: |
cd baseshift
make install
make lint
make dist

- name: Start LocalStack with extension
run: |
cd baseshift

# Baseshift clone images are private to each customer, hence we use a plain
# Postgres image as a stand-in (clones also accept connections without a password)
docker pull postgres:17

# mount the built extension into the container, so LocalStack can install it at startup
CONFIG_FILE="$(lstk config path)"
mkdir -p "$(dirname "$CONFIG_FILE")"
cat > "$CONFIG_FILE" <<EOT
[[containers]]
type = "$LOCALSTACK_EMULATOR"
tag = "$LOCALSTACK_TAG"
port = "4566"
volumes = ["$PWD/dist:/opt/extension-dist:ro"]

[cli]
check_for_update_on_startup = false
EOT

# host variables prefixed with LOCALSTACK_ are forwarded to the emulator by lstk
export LOCALSTACK_DEBUG=1
DIST_FILE="$(cd dist && ls localstack_baseshift-*.tar.gz)"
export LOCALSTACK_EXTENSION_AUTO_INSTALL="/opt/extension-dist/$DIST_FILE"
export LOCALSTACK_BASESHIFT_IMAGE=postgres:17
export LOCALSTACK_BASESHIFT_CLONE_POSTGRES_HOST_AUTH_METHOD=trust
lstk --non-interactive start

# lstk returns once LocalStack is healthy - wait until the database port is open as well
timeout 120 bash -c 'until (echo > /dev/tcp/localhost/5432) 2>/dev/null; do sleep 2; done'

- name: Run integration tests
run: |
cd baseshift
make test

- name: Run end-to-end demo
if: matrix.emulator == 'snowflake'
run: |
cd baseshift
make demo

- name: Print logs
if: always()
run: |
lstk logs --verbose
lstk stop

selfhosted-demo:
name: Run Baseshift self-hosted demo
# each run creates a new Dub in the Baseshift organization (Dubs cannot be deleted via the CLI),
# hence we skip the nightly schedule, and runs without access to the secrets (e.g., from forks)
if: github.event_name != 'schedule' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 45
env:
# unique Dub name per run - Dub names must be unique within the Baseshift organization
BASESHIFT_DUB_NAME: ci-${{ github.run_id }}-${{ github.run_attempt }}
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Install lstk CLI
# version is pinned; there is no lockfile for global CLI tools
run: | # zizmor: ignore[adhoc-packages]
npm install -g @localstack/lstk@1.2.0
lstk --version

- name: Build extension
run: |
cd baseshift
make install
make dist

- name: Start LocalStack with extension
env:
LOCALSTACK_BASESHIFT_USER_EMAIL: ${{ secrets.BASESHIFT_USER_EMAIL }}
LOCALSTACK_BASESHIFT_USER_PASSWORD: ${{ secrets.BASESHIFT_USER_PASSWORD }}
run: |
cd baseshift

CONFIG_FILE="$(lstk config path)"
mkdir -p "$(dirname "$CONFIG_FILE")"
cat > "$CONFIG_FILE" <<EOT
[[containers]]
type = "snowflake"
tag = "latest"
port = "4566"
volumes = ["$PWD/dist:/opt/extension-dist:ro"]

[cli]
check_for_update_on_startup = false
EOT

# host variables prefixed with LOCALSTACK_ are forwarded to the emulator by lstk
export LOCALSTACK_DEBUG=1
DIST_FILE="$(cd dist && ls localstack_baseshift-*.tar.gz)"
export LOCALSTACK_EXTENSION_AUTO_INSTALL="/opt/extension-dist/$DIST_FILE"
lstk --non-interactive start

- name: Run self-hosted demo
run: |
cd baseshift
make demo-selfhosted

- name: Print logs
if: always()
run: |
lstk logs --verbose
docker ps -a
docker logs "ls-baseshift-dub-$BASESHIFT_DUB_NAME-repserver" 2>&1 | tail -100 || true
lstk stop
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ You can install the respective extension by calling `localstack extensions insta
| Extension | Install name | Version | Support status |
|----------------------------------------------------------------------------------------------------| ------------ |---------| -------------- |
| [AWS Proxy](https://github.com/localstack/localstack-extensions/tree/main/aws-proxy) | localstack-extension-aws-proxy | 0.2.1 | Experimental |
| [Baseshift](https://github.com/localstack/localstack-extensions/tree/main/baseshift) | localstack-baseshift | 0.1.0 | Experimental |
| [Diagnosis Viewer](https://github.com/localstack/localstack-extensions/tree/main/diagnosis-viewer) | localstack-extension-diagnosis-viewer | 0.1.0 | Stable |
| [Hello World](https://github.com/localstack/localstack-extensions/tree/main/hello-world) | localstack-extension-hello-world | 0.1.0 | Stable |
| [httpbin](https://github.com/localstack/localstack-extensions/tree/main/httpbin) | localstack-extension-httpbin | 0.1.0 | Stable |
Expand Down
8 changes: 8 additions & 0 deletions baseshift/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.venv
dist
build
**/*.egg-info
.eggs
.pytest_cache
__pycache__
demo/.work
54 changes: 54 additions & 0 deletions baseshift/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
VENV_BIN = python3 -m venv
VENV_DIR ?= .venv
VENV_ACTIVATE = $(VENV_DIR)/bin/activate
VENV_RUN = . $(VENV_ACTIVATE)
TEST_PATH ?= tests

usage: ## Shows usage for this Makefile
@cat Makefile | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'

venv: $(VENV_ACTIVATE)

$(VENV_ACTIVATE): pyproject.toml
test -d .venv || $(VENV_BIN) .venv
$(VENV_RUN); pip install --upgrade pip setuptools plux
$(VENV_RUN); pip install -e .[dev]
touch $(VENV_DIR)/bin/activate

clean:
rm -rf .venv/
rm -rf build/
rm -rf .eggs/
rm -rf *.egg-info/

install: venv ## Install dependencies
$(VENV_RUN); python -m plux entrypoints

dist: venv ## Create distribution
$(VENV_RUN); python -m build

publish: clean-dist venv dist ## Publish extension to pypi
$(VENV_RUN); pip install --upgrade twine; twine upload dist/*

entrypoints: venv # Generate plugin entrypoints for Python package
$(VENV_RUN); python -m plux entrypoints

format: ## Run ruff to format the whole codebase
$(VENV_RUN); python -m ruff format .; python -m ruff check --output-format=full --fix .

lint: ## Run ruff to lint the codebase
$(VENV_RUN); python -m ruff check --output-format=full .

test: ## Run integration tests (requires LocalStack running with the Extension installed)
$(VENV_RUN); pytest $(PYTEST_ARGS) $(TEST_PATH)

demo: venv ## Run the end-to-end demo (requires LocalStack with the Snowflake emulator and the Extension installed)
$(VENV_RUN); pip install -q -r demo/requirements.txt; python demo/demo.py all

demo-selfhosted: venv ## Run the end-to-end demo with the Baseshift self-hosted components (requires LocalStack started with BASESHIFT_USER_EMAIL/PASSWORD)
$(VENV_RUN); pip install -q -r demo/requirements.txt; python demo/demo.py all --selfhosted

clean-dist: clean
rm -rf dist/

.PHONY: clean clean-dist demo demo-selfhosted dist install publish usage venv format lint test
Loading
Loading