Skip to content
Merged
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
20 changes: 7 additions & 13 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ jobs:
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
AWS_CONFIG_FILE: scripts/demo-aws-config/config
AWS_SHARED_CREDENTIALS_FILE: scripts/demo-aws-config/credentials
LOCALSTACK_IMAGE: localstack/localstack:4.12.0
steps:
- uses: actions/checkout@v6

Expand All @@ -27,12 +30,14 @@ jobs:
go-version-file: 'go.mod'
cache: true

- uses: cachix/install-nix-action@6b2916c41eac5735ac995c58c9e8561a78c42319 # v31

- name: Build
run: go build -o claws ./cmd/claws

- name: Start LocalStack
run: |
docker run -d --name localstack -p 4566:4566 localstack/localstack:4.12.0
docker run -d --name localstack -p 4566:4566 "${LOCALSTACK_IMAGE}"
echo "Waiting for LocalStack..."
for i in $(seq 1 30); do
if curl -s http://localhost:4566/_localstack/health | grep -qE '"s3": "(available|running)"'; then
Expand All @@ -48,25 +53,14 @@ jobs:
timeout-minutes: 5
run: ./scripts/localstack-demo-setup.sh

- name: Create AWS config for demo
run: |
mkdir -p ~/.aws
cp scripts/demo-aws-config/config ~/.aws/config
cp scripts/demo-aws-config/credentials ~/.aws/credentials

- name: Run VHS tapes
run: |
set -e
for tape in docs/tapes/*.tape; do
echo "=========================================="
echo "Running: $tape"
echo "=========================================="
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v ~/.aws:/root/.aws:ro \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs "$tape"
nix develop --command vhs "$tape"
done

- name: Upload screenshots on failure
Expand Down
132 changes: 73 additions & 59 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ version: '3'

vars:
LOCALSTACK_CONTAINER: claws-localstack
LOCALSTACK_IMAGE: localstack/localstack:4.12.0

tasks:
build:
Expand Down Expand Up @@ -33,9 +34,9 @@ tasks:

# LocalStack tasks
localstack:start:
desc: Start LocalStack container
desc: Start pinned LocalStack container
cmds:
- docker start {{.LOCALSTACK_CONTAINER}} 2>/dev/null || docker run -d --name {{.LOCALSTACK_CONTAINER}} -p 4566:4566 localstack/localstack:4.12.0
- docker start {{.LOCALSTACK_CONTAINER}} 2>/dev/null || docker run -d --name {{.LOCALSTACK_CONTAINER}} -p 4566:4566 {{.LOCALSTACK_IMAGE}}
- |
echo "Waiting for LocalStack to be ready..."
for i in $(seq 1 30); do
Expand Down Expand Up @@ -99,11 +100,11 @@ tasks:
- ./claws

demo:record:
desc: Record all demos (gif + screenshots) using VHS + LocalStack
desc: Record all demos (gif + screenshots) using host VHS + LocalStack
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
- sh: command -v vhs >/dev/null 2>&1
msg: "vhs is required. Install it locally before running demo recording tasks."
cmds:
- task: demo:record:gif
- task: demo:record:themes
Expand All @@ -115,96 +116,109 @@ tasks:
desc: Record demo.gif only
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
- sh: command -v vhs >/dev/null 2>&1
msg: "vhs is required. Install it locally before running demo recording tasks."
env:
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
AWS_CONFIG_FILE: scripts/demo-aws-config/config
AWS_SHARED_CREDENTIALS_FILE: scripts/demo-aws-config/credentials
cmds:
- |
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/demo.tape
- vhs docs/tapes/demo.tape

demo:record:themes:
desc: Record theme screenshots only
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
- sh: command -v vhs >/dev/null 2>&1
msg: "vhs is required. Install it locally before running demo recording tasks."
env:
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
AWS_CONFIG_FILE: scripts/demo-aws-config/config
AWS_SHARED_CREDENTIALS_FILE: scripts/demo-aws-config/credentials
cmds:
- |
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/themes.tape
- vhs docs/tapes/themes.tape

demo:record:features:
desc: Record feature screenshots only
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
- sh: command -v vhs >/dev/null 2>&1
msg: "vhs is required. Install it locally before running demo recording tasks."
env:
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
AWS_CONFIG_FILE: scripts/demo-aws-config/config
AWS_SHARED_CREDENTIALS_FILE: scripts/demo-aws-config/credentials
cmds:
- |
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/features.tape
- vhs docs/tapes/features.tape

demo:record:theme-light:
desc: Record light theme screenshot (requires white terminal background)
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
- sh: command -v vhs >/dev/null 2>&1
msg: "vhs is required. Install it locally before running demo recording tasks."
env:
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
AWS_CONFIG_FILE: scripts/demo-aws-config/config
AWS_SHARED_CREDENTIALS_FILE: scripts/demo-aws-config/credentials
cmds:
- |
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/theme-light.tape
- vhs docs/tapes/theme-light.tape

demo:record:command-mode:
desc: Record command mode suggestion/completion test
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "demo:record requires Linux (--network host not supported on macOS/Windows)"
- sh: command -v vhs >/dev/null 2>&1
msg: "vhs is required. Install it locally before running demo recording tasks."
env:
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
AWS_CONFIG_FILE: scripts/demo-aws-config/config
AWS_SHARED_CREDENTIALS_FILE: scripts/demo-aws-config/credentials
cmds:
- |
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs docs/tapes/command-mode.tape
- vhs docs/tapes/command-mode.tape

test:vhs:
desc: Run all VHS tapes as integration tests
desc: Run all VHS tapes as integration tests using host VHS
deps: [build, localstack:start, localstack:demo-setup]
preconditions:
- sh: '[ "$(uname -s)" = "Linux" ]'
msg: "test:vhs requires Linux (--network host not supported on macOS/Windows)"
- sh: command -v vhs >/dev/null 2>&1
msg: "vhs is required. Install it locally before running VHS integration tests."
env:
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_EC2_METADATA_DISABLED: "true"
AWS_CONFIG_FILE: scripts/demo-aws-config/config
AWS_SHARED_CREDENTIALS_FILE: scripts/demo-aws-config/credentials
cmds:
- |
set -e
for tape in docs/tapes/*.tape; do
echo "=========================================="
echo "Running: $tape"
echo "=========================================="
docker run --rm --network host \
-v "$(pwd)":/vhs \
-v "$(pwd)/scripts/demo-aws-config:/root/.aws:ro" \
-e AWS_ENDPOINT_URL=http://localhost:4566 \
-e AWS_EC2_METADATA_DISABLED=true \
ghcr.io/charmbracelet/vhs "$tape"
vhs "$tape"
done

test-localstack:
Expand Down
49 changes: 41 additions & 8 deletions custom/events/rules/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package rules

import (
"context"
"strings"

"github.com/aws/aws-sdk-go-v2/service/eventbridge"
"github.com/aws/aws-sdk-go-v2/service/eventbridge/types"
Expand Down Expand Up @@ -61,8 +62,12 @@ func (d *RuleDAO) List(ctx context.Context) ([]dao.Resource, error) {
}

func (d *RuleDAO) Get(ctx context.Context, id string) (dao.Resource, error) {
ruleName, eventBusName := parseRuleID(id)
input := &eventbridge.DescribeRuleInput{
Name: &id,
Name: &ruleName,
}
if eventBusName != "" {
input.EventBusName = &eventBusName
}

output, err := d.client.DescribeRule(ctx, input)
Expand Down Expand Up @@ -90,7 +95,7 @@ func (d *RuleDAO) Get(ctx context.Context, id string) (dao.Resource, error) {

// Fetch targets
targetsInput := &eventbridge.ListTargetsByRuleInput{
Rule: &id,
Rule: &ruleName,
EventBusName: output.EventBusName,
}
if targetsOutput, err := d.client.ListTargetsByRule(ctx, targetsInput); err == nil {
Expand All @@ -101,9 +106,13 @@ func (d *RuleDAO) Get(ctx context.Context, id string) (dao.Resource, error) {
}

func (d *RuleDAO) Delete(ctx context.Context, id string) error {
ruleName, eventBusName := parseRuleID(id)
// First, need to remove all targets
targetsInput := &eventbridge.ListTargetsByRuleInput{
Rule: &id,
Rule: &ruleName,
}
if eventBusName != "" {
targetsInput.EventBusName = &eventBusName
}
targetsOutput, err := d.client.ListTargetsByRule(ctx, targetsInput)
if err == nil && len(targetsOutput.Targets) > 0 {
Expand All @@ -114,18 +123,25 @@ func (d *RuleDAO) Delete(ctx context.Context, id string) error {
}
}
if len(targetIds) > 0 {
_, err = d.client.RemoveTargets(ctx, &eventbridge.RemoveTargetsInput{
Rule: &id,
removeInput := &eventbridge.RemoveTargetsInput{
Rule: &ruleName,
Ids: targetIds,
})
}
if eventBusName != "" {
removeInput.EventBusName = &eventBusName
}
_, err = d.client.RemoveTargets(ctx, removeInput)
if err != nil {
return apperrors.Wrapf(err, "remove targets for rule %s", id)
}
}
}

input := &eventbridge.DeleteRuleInput{
Name: &id,
Name: &ruleName,
}
if eventBusName != "" {
input.EventBusName = &eventBusName
}

_, err = d.client.DeleteRule(ctx, input)
Expand All @@ -147,10 +163,12 @@ type RuleResource struct {
// NewRuleResource creates a new RuleResource
func NewRuleResource(rule types.Rule) *RuleResource {
name := appaws.Str(rule.Name)
eventBusName := appaws.Str(rule.EventBusName)
id := ruleID(name, eventBusName)

return &RuleResource{
BaseResource: dao.BaseResource{
ID: name,
ID: id,
Name: name,
ARN: appaws.Str(rule.Arn),
Tags: nil,
Expand All @@ -160,6 +178,21 @@ func NewRuleResource(rule types.Rule) *RuleResource {
}
}

func ruleID(name, eventBusName string) string {
if eventBusName == "" {
return name
}
return eventBusName + "/" + name
}

func parseRuleID(id string) (name, eventBusName string) {
idx := strings.LastIndex(id, "/")
if idx < 0 {
return id, ""
}
return id[idx+1:], id[:idx]
}

// ARN returns the rule ARN
func (r *RuleResource) ARN() string {
if r.Item.Arn != nil {
Expand Down
Loading
Loading