Skip to content
Open
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
f66f8e2
test: add antithesis test
gfyrag Nov 12, 2024
df41f3d
chore: some test
gfyrag Nov 13, 2024
eead415
feat: first workable setup
gfyrag Nov 13, 2024
3b91230
Merge branch 'main' of github.com:formancehq/ledger into feat/dst
altitude Feb 21, 2025
24c347a
wip: bring up to date and new driver
altitude Feb 21, 2025
0addc57
fix: test composer changes
altitude Mar 13, 2025
dc15569
Merge branch 'main' of github.com:formancehq/ledger into feat/dst
altitude Mar 13, 2025
d64d1ef
wip: improve assertions
altitude Mar 13, 2025
32759cc
fix: overly ambitious assertions
altitude Mar 13, 2025
a380c0b
wip: add debugger
altitude Mar 13, 2025
b22e498
Merge remote-tracking branch 'origin/main' into feat/dst
altitude Apr 23, 2025
0919823
feat: add antithesis ci
altitude Apr 23, 2025
8aa8fb7
fix: antithesis registry docker login
altitude Apr 23, 2025
6d3747a
fix: antithesis docker login
altitude Apr 23, 2025
256bfb9
fix: antithesis github workflow
altitude Apr 23, 2025
10acc49
fix: workload build
altitude Apr 23, 2025
a2351d6
feat: improve test composing sequence
altitude May 2, 2025
58524d7
feat: improve test composer sequence
altitude May 5, 2025
4ed1eb5
fix: volumes driver
altitude May 5, 2025
8aaa393
fix: don't overuse assertions
altitude May 5, 2025
3ec2e4c
fix: ledger id
altitude May 5, 2025
9f22e06
fix: bucket/ledger
altitude May 5, 2025
aa9fa2b
Merge remote-tracking branch 'origin/main' into feat/dst
altitude May 5, 2025
e8b6e82
fix: remove exhaustive assertion on tx
altitude May 5, 2025
9fc1cf7
fix: switch to sometimes assertions for tx commit
altitude May 5, 2025
e52be33
feat: switch ledger creation to sometimes assertions as well
altitude May 5, 2025
40c1a39
fix: move correctness check to eventually
altitude May 5, 2025
c8ab708
feat: improve error handling on eventually
altitude May 6, 2025
f8fa1ba
Merge remote-tracking branch 'origin/main' into feat/dst
altitude May 6, 2025
979b33a
fix: improve error handling
altitude May 6, 2025
49b0414
wip: improve
altitude May 7, 2025
9248bd8
feat: add Kubernetes pod configuration for workload
flemzord Jun 19, 2025
424b4c1
k8s test setup
Azorlogh Aug 13, 2025
d4f161b
Merge branch 'main' into feat/dst-k8s
Azorlogh Aug 13, 2025
c5dac59
test fixes & remove docker-compose antithesis setup
Azorlogh Aug 18, 2025
7664eb6
integrate the operator
Azorlogh Aug 27, 2025
0966637
partially fix ledger instrumentation
Azorlogh Sep 3, 2025
c152718
fixes, readiness probe, missing images
Azorlogh Sep 8, 2025
0f879a9
fix workload panic
Azorlogh Sep 9, 2025
c3cb880
remove main earthfile & fix workflow
Azorlogh Sep 9, 2025
9db3f81
fix secret name
Azorlogh Sep 9, 2025
fddeb96
use antithesis-trigger-action
Azorlogh Sep 9, 2025
fa66ba7
fix images list
Azorlogh Sep 9, 2025
62309de
keep just setup for now
Azorlogh Sep 9, 2025
1ee5795
version upgrades & specify tags in workflow
Azorlogh Sep 10, 2025
65042d5
test run
Azorlogh Sep 10, 2025
af6956b
fix workflow
Azorlogh Sep 10, 2025
59ddcbf
fix workflow
Azorlogh Sep 10, 2025
3242e71
fix missing images
Azorlogh Sep 10, 2025
3c8a68b
fix token
Azorlogh Sep 10, 2025
d2d57b7
fix version update command & workload permissions
Azorlogh Sep 10, 2025
0484df1
temporarily disable version update, more complex workload & checks
Azorlogh Sep 23, 2025
a5e3d61
fix instrumented ledger release workflow
Azorlogh Sep 23, 2025
6b8fd2e
rerun workflow & fix names
Azorlogh Sep 23, 2025
f51e01f
workflow fixes
Azorlogh Sep 23, 2025
47401f6
workload fixes
Azorlogh Sep 23, 2025
c40afec
more assertion details
Azorlogh Sep 24, 2025
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
91 changes: 91 additions & 0 deletions .github/workflows/antithesis_daily.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Antithesis Integration
on:
workflow_dispatch:
inputs:
run_tests:
description: "Run Antithesis tests after pushing images"
type: boolean
default: true
# push:
# branches:
# - main
pull_request:
types: [opened, synchronize, reopened]
paths:
- "test/antithesis/**"
schedule:
- cron: "0 10 * * *"

jobs:
push-antithesis-images:
name: Push Images to Antithesis
runs-on: shipfox-4vcpu-ubuntu-2404
env:
ANTITHESIS_PASSWORD: ${{ secrets.ANTITHESIS_PASSWORD }}
ANTITHESIS_SLACK_REPORT_RECIPIENT: ${{ secrets.ANTITHESIS_SLACK_REPORT_RECIPIENT }}
ANTITHESIS_REPOSITORY: ${{ secrets.ANTITHESIS_REPOSITORY }}
OPERATOR_TAG: "v2.10.1"
OPERATOR_UTILS_TAG: "v2.0.14"
GATEWAY_TAG: "v2.0.24"
# LEDGER_PREVIOUS_TAG: "v2.2.47"
# temporary: remove this when support for multiple image versions is added
LEDGER_PREVIOUS_TAG: "v2.3.0"
LEDGER_LATEST_TAG: "v2.3.0"
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Earthly
uses: earthly/actions-setup@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
version: "latest"

- name: Setup Just
uses: extractions/setup-just@v3
with:
just-version: "1.40.0"

- name: Setup Environment
uses: ./.github/actions/default
with:
token: ${{ secrets.NUMARY_GITHUB_TOKEN }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: "NumaryBot"
password: ${{ secrets.NUMARY_GITHUB_TOKEN }}

- name: Login to Antithesis Docker Registry
run: |
echo '${{ secrets.ANTITHESIS_JSON_KEY }}' | docker login -u _json_key https://us-central1-docker.pkg.dev --password-stdin

- name: Build and Push Config Image
run: |
cd test/antithesis
just requirements-build

- name: Run Antithesis Tests
# if: ${{ github.event_name == 'workflow_dispatch' && inputs.run_tests == true }}
uses: antithesishq/antithesis-trigger-action@v0.8
with:
notebook_name: formance-k8s
tenant: formance
username: ${{ secrets.ANTITHESIS_USERNAME }}
password: ${{ secrets.ANTITHESIS_PASSWORD }}
github_token: ${{ secrets.NUMARY_GITHUB_TOKEN }}
# images: "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:${{ env.OPERATOR_TAG }};ghcr.io/formancehq/operator-utils:${{ env.OPERATOR_UTILS_TAG }};ghcr.io/formancehq/gateway:${{ env.GATEWAY_TAG }};ghcr.io/formancehq/ledger-instrumented:${{ env.LEDGER_PREVIOUS_TAG }};ghcr.io/formancehq/ledger-instrumented:${{ env.LEDGER_LATEST_TAG }}"
# temporary: remove this when support for multiple image versions is added
images: "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:${{ env.OPERATOR_TAG }};ghcr.io/formancehq/operator-utils:${{ env.OPERATOR_UTILS_TAG }};ghcr.io/formancehq/gateway:${{ env.GATEWAY_TAG }};ghcr.io/formancehq/ledger-instrumented:${{ env.LEDGER_LATEST_TAG }}"
config_image: "antithesis-config:k8s_test"
email_recipients: ${{ secrets.ANTITHESIS_SLACK_REPORT_RECIPIENT }}
53 changes: 53 additions & 0 deletions .github/workflows/antithesis_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Antithesis Integration
on:
push:
tags:
- "*"

jobs:
push-antithesis-images:
name: Push Images to Antithesis
runs-on: shipfox-4vcpu-ubuntu-2404
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Earthly
uses: earthly/actions-setup@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
version: "latest"

- name: Setup Just
uses: extractions/setup-just@v3
with:
just-version: "1.40.0"

- name: Setup Environment
uses: ./.github/actions/default
with:
token: ${{ secrets.NUMARY_GITHUB_TOKEN }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: "NumaryBot"
password: ${{ secrets.NUMARY_GITHUB_TOKEN }}

- name: Login to Antithesis Docker Registry
run: |
echo '${{ secrets.ANTITHESIS_JSON_KEY }}' | docker login -u _json_key https://us-central1-docker.pkg.dev --password-stdin

- name: Build and Push Config Image
run: |
cd test/antithesis/image
earthly --push ./image+build --ANTITHESIS_REPOSITORY="${{ secrets.ANTITHESIS_REPOSITORY }}" --LEDGER_LATEST_TAG="${{ env.GITHUB_REF_NAME }}"
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ replace google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215 => google.
require (
github.com/ThreeDotsLabs/watermill v1.4.7
github.com/alitto/pond v1.9.2
github.com/antithesishq/antithesis-sdk-go v0.4.3
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10
github.com/bluele/gcache v0.0.2
github.com/dop251/goja v0.0.0-20250630131328-58d95d85e994
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7X
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op h1:+OSa/t11TFhqfrX0EOSqQBDJ0YlpmK0rDSiB19dg9M0=
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E=
github.com/antithesishq/antithesis-sdk-go v0.4.3 h1:a2hGdDogClzHzFu20r1z0tzD6zwSWUipiaerAjZVP90=
github.com/antithesishq/antithesis-sdk-go v0.4.3/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E=
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
Expand Down
42 changes: 39 additions & 3 deletions internal/storage/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"context"
"errors"
"fmt"
"sync"
"time"

"github.com/antithesishq/antithesis-sdk-go/assert"
"github.com/formancehq/ledger/internal/storage/common"
systemstore "github.com/formancehq/ledger/internal/storage/system"
"github.com/formancehq/ledger/internal/tracing"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
"sync"
"time"

"github.com/alitto/pond"
"github.com/formancehq/go-libs/v3/bun/bunpaginate"
Expand All @@ -36,13 +38,31 @@ type Driver struct {
parallelBucketMigrations int
}

func (d *Driver) CreateLedger(ctx context.Context, l *ledger.Ledger) (*ledgerstore.Store, error) {
/*
CreateLedger creates a new ledger in the system and sets up all necessary database objects.

The function follows these steps:
1. Create a ledger record in the system store (_system.ledgers table)
2. Get the bucket (database schema) for this ledger
3. Check if the bucket is already initialized:
a. If initialized: Verify it's up to date and add ledger-specific objects to it
b. If not initialized: Create the bucket schema with all necessary tables
4. Return a ledger store that provides an interface to interact with the ledger

Note: This entire process is wrapped in a database transaction, ensuring atomicity.
If any step fails, the entire transaction is rolled back, preventing partial state.
*/
func (d *Driver) CreateLedger(ctx context.Context, l *ledger.Ledger) (*ledgerstore.Store, error) {
var ret *ledgerstore.Store

// Run the entire ledger creation process in a transaction for atomicity
// This ensures that either all steps succeed or none do (preventing partial state)
err := d.db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
systemStore := d.systemStoreFactory.Create(tx)

// Step 1: Create the ledger record in the system store
if err := systemStore.CreateLedger(ctx, l); err != nil {
// Handle the case where the ledger already exists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know comments are useful, but this kind of comment just rephrase the code ^^

if errors.Is(postgres.ResolveError(err), postgres.ErrConstraintsFailed{}) {
return systemstore.ErrLedgerAlreadyExists
}
Expand All @@ -54,13 +74,25 @@ func (d *Driver) CreateLedger(ctx context.Context, l *ledger.Ledger) (*ledgersto
if err != nil {
return fmt.Errorf("checking if bucket is initialized: %w", err)
}

if isInitialized {
upToDate, err := b.IsUpToDate(ctx, tx)
if err != nil {
return fmt.Errorf("checking if bucket is up to date: %w", err)
}

if !upToDate {
assert.AlwaysOrUnreachable(
// @todo: replace this with a proper flag detailing wether we're
// operating a new version of the binary or not.
// if we are, we are definitely expecting this to happen.
// if we're not, this should be unreachable.
false,
"Bucket is outdated",
map[string]any{
"bucket": l.Bucket,
},
)
return ErrBucketOutdated
}

Expand All @@ -73,14 +105,18 @@ func (d *Driver) CreateLedger(ctx context.Context, l *ledger.Ledger) (*ledgersto
}
}

// Step 4: Create a store for interacting with the ledger
ret = d.ledgerStoreFactory.Create(b, *l)

return nil
})

// If any error occurred during the transaction, resolve and return it
if err != nil {
return nil, postgres.ResolveError(err)
}

// Return the created ledger store
return ret, nil
}

Expand Down
8 changes: 8 additions & 0 deletions pkg/client/Earthfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
VERSION 0.7
Copy link
Contributor

@gfyrag gfyrag Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stop using Earthfile, there is no Earthfile anymore in the repsoitory ;)


FROM --platform=linux/amd64 golang:1.22.2

client:
FROM scratch
COPY . /client
SAVE ARTIFACT /client client
27 changes: 27 additions & 0 deletions test/antithesis/Justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
run-6min: requirements-build
curl --fail \
--user "formance:$ANTITHESIS_PASSWORD" \
-X POST https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s -d '{ \
"params": { \
"custom.duration": "0.1", \
"antithesis.report.recipients": "'"$ANTITHESIS_SLACK_REPORT_RECIPIENT"'", \
"antithesis.config_image": "antithesis-config:k8s_test", \
"antithesis.images": "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:v2.10.1;ghcr.io/formancehq/operator-utils:v2.0.14;ghcr.io/formancehq/gateway:v2.0.24;ghcr.io/formancehq/ledger-instrumented:k8s_test" \
} \
}'
Comment on lines +2 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Stop leaking credentials; switch to netrc, add JSON header, and harden curl.

Passing $ANTITHESIS_PASSWORD via --user exposes it in process listings. Also, set the proper JSON content-type and add basic resiliency.

Apply this diff:

-    curl --fail \
-        --user "formance:$ANTITHESIS_PASSWORD" \
-        -X POST https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s -d '{ \
+    # Preconditions & secure auth (avoid exposing secrets in process list)
+    : "${ANTITHESIS_PASSWORD:?ANTITHESIS_PASSWORD is required}"
+    : "${ANTITHESIS_SLACK_REPORT_RECIPIENT:?ANTITHESIS_SLACK_REPORT_RECIPIENT is required}"
+    tmp_netrc="$(mktemp)"; trap 'rm -f "$tmp_netrc"' EXIT
+    printf 'machine formance.antithesis.com login formance password %s\n' "$ANTITHESIS_PASSWORD" > "$tmp_netrc"
+    chmod 600 "$tmp_netrc"
+    curl --fail --silent --show-error --retry 3 --retry-all-errors \
+        --netrc-file "$tmp_netrc" \
+        -H 'Content-Type: application/json' \
+        -X POST 'https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s' -d '{ \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
curl --fail \
--user "formance:$ANTITHESIS_PASSWORD" \
-X POST https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s -d '{ \
"params": { \
"custom.duration": "0.1", \
"antithesis.report.recipients": "'"$ANTITHESIS_SLACK_REPORT_RECIPIENT"'", \
"antithesis.config_image": "antithesis-config:k8s_test", \
"antithesis.images": "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:v2.10.1;ghcr.io/formancehq/operator-utils:v2.0.14;ghcr.io/formancehq/gateway:v2.0.24;ghcr.io/formancehq/ledger-instrumented:k8s_test" \
} \
}'
# Preconditions & secure auth (avoid exposing secrets in process list)
: "${ANTITHESIS_PASSWORD:?ANTITHESIS_PASSWORD is required}"
: "${ANTITHESIS_SLACK_REPORT_RECIPIENT:?ANTITHESIS_SLACK_REPORT_RECIPIENT is required}"
tmp_netrc="$(mktemp)"; trap 'rm -f "$tmp_netrc"' EXIT
printf 'machine formance.antithesis.com login formance password %s\n' "$ANTITHESIS_PASSWORD" > "$tmp_netrc"
chmod 600 "$tmp_netrc"
curl --fail --silent --show-error --retry 3 --retry-all-errors \
--netrc-file "$tmp_netrc" \
-H 'Content-Type: application/json' \
-X POST 'https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s' -d '{ \
"params": { \
"custom.duration": "0.1", \
"antithesis.report.recipients": "'"$ANTITHESIS_SLACK_REPORT_RECIPIENT"'", \
"antithesis.config_image": "antithesis-config:k8s_test", \
"antithesis.images": "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:v2.10.1;ghcr.io/formancehq/operator-utils:v2.0.14;ghcr.io/formancehq/gateway:v2.0.24;ghcr.io/formancehq/ledger-instrumented:k8s_test" \
} \
}'
🤖 Prompt for AI Agents
In test/antithesis/Justfile around lines 2 to 11, the curl invocation leaks the
ANTITHESIS_PASSWORD via --user, lacks a JSON content-type header, and has no
retry/resilience flags; remove the --user usage and instead rely on netrc by
instructing the environment or CI to create a .netrc entry for the host with the
Formance credentials and pass curl the netrc file option, add a Content-Type:
application/json header, and harden curl by adding --silent --show-error --fail
--location plus retry flags (e.g., --retry and --retry-delay) to improve
resiliency; ensure data remains JSON-encoded and that secret handling is
documented so the .netrc is created with correct permissions before running this
command.


run-1h: requirements-build
curl --fail \
--user "formance:$ANTITHESIS_PASSWORD" \
-X POST https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s -d '{ \
"params": { \
"custom.duration": "1", \
"antithesis.report.recipients": "'"$ANTITHESIS_SLACK_REPORT_RECIPIENT"'", \
"antithesis.config_image": "antithesis-config:k8s_test", \
"antithesis.images": "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:v2.10.1;ghcr.io/formancehq/operator-utils:v2.0.14;ghcr.io/formancehq/gateway:v2.0.24;ghcr.io/formancehq/ledger-instrumented:k8s_test" \
} \
}'
Comment on lines +14 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Mirror the security and resiliency fixes in run-1h.

Apply the same netrc, JSON header, and curl hardening here.

-    curl --fail \
-        --user "formance:$ANTITHESIS_PASSWORD" \
-        -X POST https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s -d '{ \
+    : "${ANTITHESIS_PASSWORD:?ANTITHESIS_PASSWORD is required}"
+    : "${ANTITHESIS_SLACK_REPORT_RECIPIENT:?ANTITHESIS_SLACK_REPORT_RECIPIENT is required}"
+    tmp_netrc="$(mktemp)"; trap 'rm -f "$tmp_netrc"' EXIT
+    printf 'machine formance.antithesis.com login formance password %s\n' "$ANTITHESIS_PASSWORD" > "$tmp_netrc"
+    chmod 600 "$tmp_netrc"
+    curl --fail --silent --show-error --retry 3 --retry-all-errors \
+        --netrc-file "$tmp_netrc" \
+        -H 'Content-Type: application/json' \
+        -X POST 'https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s' -d '{ \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
curl --fail \
--user "formance:$ANTITHESIS_PASSWORD" \
-X POST https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s -d '{ \
"params": { \
"custom.duration": "1", \
"antithesis.report.recipients": "'"$ANTITHESIS_SLACK_REPORT_RECIPIENT"'", \
"antithesis.config_image": "antithesis-config:k8s_test", \
"antithesis.images": "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:v2.10.1;ghcr.io/formancehq/operator-utils:v2.0.14;ghcr.io/formancehq/gateway:v2.0.24;ghcr.io/formancehq/ledger-instrumented:k8s_test" \
} \
}'
: "${ANTITHESIS_PASSWORD:?ANTITHESIS_PASSWORD is required}"
: "${ANTITHESIS_SLACK_REPORT_RECIPIENT:?ANTITHESIS_SLACK_REPORT_RECIPIENT is required}"
tmp_netrc="$(mktemp)"; trap 'rm -f "$tmp_netrc"' EXIT
printf 'machine formance.antithesis.com login formance password %s\n' "$ANTITHESIS_PASSWORD" > "$tmp_netrc"
chmod 600 "$tmp_netrc"
curl --fail --silent --show-error --retry 3 --retry-all-errors \
--netrc-file "$tmp_netrc" \
-H 'Content-Type: application/json' \
-X POST 'https://formance.antithesis.com/api/v1/launch_experiment/formance-k8s' -d '{ \
"params": { \
"custom.duration": "1", \
"antithesis.report.recipients": "'"$ANTITHESIS_SLACK_REPORT_RECIPIENT"'", \
"antithesis.config_image": "antithesis-config:k8s_test", \
"antithesis.images": "workload:latest;docker.io/library/postgres:15-alpine;ghcr.io/formancehq/operator:v2.10.1;ghcr.io/formancehq/operator-utils:v2.0.14;ghcr.io/formancehq/gateway:v2.0.24;ghcr.io/formancehq/ledger-instrumented:k8s_test" \
} \
}'
🤖 Prompt for AI Agents
In test/antithesis/Justfile around lines 14 to 23, the curl call lacks the same
security and resiliency flags used in run-1h; update the invocation to use a
netrc file for credentials (e.g. --netrc-file "$ANTITHESIS_NETRC" or --netrc as
appropriate), add an explicit JSON content-type header (-H "Content-Type:
application/json"), and harden curl by adding standard options such as --silent
--show-error --location --fail --retry N --retry-delay M --connect-timeout S
--max-time T (choose sensible values) so the request uses the netrc credentials,
sends proper JSON headers, follows redirects, surfaces errors, and
retries/timeouts for resilience.


requirements-build:
just config/push
earthly --push ./workload+build --ANTITHESIS_REPOSITORY="$ANTITHESIS_REPOSITORY" --LEDGER_LATEST_TAG="$LEDGER_LATEST_TAG"
1 change: 1 addition & 0 deletions test/antithesis/config/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tmp
2 changes: 2 additions & 0 deletions test/antithesis/config/Dockerfile.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM scratch
COPY tmp/* /manifests/
19 changes: 19 additions & 0 deletions test/antithesis/config/Justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
build-manifest:
rm -f -- tmp/resources.yaml
mkdir -p tmp
cat manifests/namespace.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/postgres.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
helm template regions oci://ghcr.io/formancehq/helm/regions --version 2.15.2 --namespace formance-systems >> tmp/resources.yaml
# helm template operator oci://ghcr.io/formancehq/helm/operator-crds --version v2.8.0 --namespace formance-systems >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/stack.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
yq '.spec.version = strenv(LEDGER_PREVIOUS_TAG)' manifests/ledger.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/workload.yaml >> tmp/resources.yaml

Comment on lines +1 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Harden recipes: fail fast and guard required env.

Add strict shell flags and verify LEDGER_PREVIOUS_TAG is set before templating.

 build-manifest:
-	rm -f -- tmp/resources.yaml
+	set -euo pipefail
+	: "${LEDGER_PREVIOUS_TAG:?LEDGER_PREVIOUS_TAG is required}"
+	rm -f -- tmp/resources.yaml
 	mkdir -p tmp
 	cat manifests/namespace.yaml >> tmp/resources.yaml
 	echo "---" >> tmp/resources.yaml
 	cat manifests/postgres.yaml >> tmp/resources.yaml
 	echo "---" >> tmp/resources.yaml
 	helm template regions oci://ghcr.io/formancehq/helm/regions --version 2.15.2 --namespace formance-systems >> tmp/resources.yaml
 	# helm template operator oci://ghcr.io/formancehq/helm/operator-crds --version v2.8.0 --namespace formance-systems >> tmp/resources.yaml
 	echo "---" >> tmp/resources.yaml
 	cat manifests/stack.yaml >> tmp/resources.yaml
 	echo "---" >> tmp/resources.yaml
 	yq '.spec.version = strenv(LEDGER_PREVIOUS_TAG)' manifests/ledger.yaml >> tmp/resources.yaml
 	echo "---" >> tmp/resources.yaml
 	cat manifests/workload.yaml >> tmp/resources.yaml
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
build-manifest:
rm -f -- tmp/resources.yaml
mkdir -p tmp
cat manifests/namespace.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/postgres.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
helm template regions oci://ghcr.io/formancehq/helm/regions --version 2.15.2 --namespace formance-systems >> tmp/resources.yaml
# helm template operator oci://ghcr.io/formancehq/helm/operator-crds --version v2.8.0 --namespace formance-systems >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/stack.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
yq '.spec.version = strenv(LEDGER_PREVIOUS_TAG)' manifests/ledger.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/workload.yaml >> tmp/resources.yaml
build-manifest:
set -euo pipefail
: "${LEDGER_PREVIOUS_TAG:?LEDGER_PREVIOUS_TAG is required}"
rm -f -- tmp/resources.yaml
mkdir -p tmp
cat manifests/namespace.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/postgres.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
helm template regions oci://ghcr.io/formancehq/helm/regions --version 2.15.2 --namespace formance-systems >> tmp/resources.yaml
# helm template operator oci://ghcr.io/formancehq/helm/operator-crds --version v2.8.0 --namespace formance-systems >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/stack.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
yq '.spec.version = strenv(LEDGER_PREVIOUS_TAG)' manifests/ledger.yaml >> tmp/resources.yaml
echo "---" >> tmp/resources.yaml
cat manifests/workload.yaml >> tmp/resources.yaml
🤖 Prompt for AI Agents
In test/antithesis/config/Justfile around lines 1 to 16, the build-manifest
recipe runs multiple shell commands without strict failure handling or checking
required environment variables; update the recipe to enable strict shell flags
(set -euo pipefail) at the start of the recipe’s shell invocation and add an
explicit guard that verifies LEDGER_PREVIOUS_TAG is set (exit with a clear error
if not) before running the yq templating step so the recipe fails fast and does
not proceed with an unset variable.

push: build-manifest
docker build -f Dockerfile.config -t $ANTITHESIS_REPOSITORY/antithesis-config:k8s_test .
docker push $ANTITHESIS_REPOSITORY/antithesis-config:k8s_test
7 changes: 7 additions & 0 deletions test/antithesis/config/manifests/ledger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: formance.com/v1beta1
kind: Ledger
metadata:
name: stack0-ledger
spec:
stack: stack0
version: LEDGER_VERSION_PLACEHOLDER
4 changes: 4 additions & 0 deletions test/antithesis/config/manifests/namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: formance-systems
42 changes: 42 additions & 0 deletions test/antithesis/config/manifests/postgres.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: formance-systems
spec:
selector:
app: postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432
---
apiVersion: v1
kind: Pod
metadata:
name: postgres
namespace: formance-systems
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15-alpine
imagePullPolicy: IfNotPresent
args: ["-c", "max_connections=100"]
env:
- name: "POSTGRES_USER"
value: "ledger"
- name: "POSTGRES_PASSWORD"
value: "ledger"
- name: "POSTGRES_DB"
value: "ledger"
- name: "PGDATA"
value: /data/postgres
livenessProbe:
exec:
command: ["pg_isready", "-Uledger"]
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 5
Loading
Loading