Skip to content
Closed
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
57 changes: 57 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Rust

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

env:
CARGO_TERM_COLOR: always
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres

jobs:
test:
runs-on: ubuntu-latest

services:
# We can use the service container directly or run docker-compose
# Using docker-compose as requested to ensure it matches local setup
postgres:
image: postgres:17-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
# Health check to ensure postgres is ready before starting the job
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- uses: actions/checkout@v4

- name: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Rust Cache
uses: Swatinem/rust-cache@v2

- name: Initialize role
run: |
PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -f 1_role.sql
working-directory: ./fly-app/sql


- name: Initialize database
run: |
PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -f dump.sql
working-directory: ./fly-app/sql

- name: Run tests
run: cargo test
working-directory: ./fly-app
10 changes: 10 additions & 0 deletions fly-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Creating DB dump
Run `./bin/create_db_dump.sh <full PG url with password>`
## Running tests
1. run `docker-compose up -d` to start local PG database
2. `cargo test`
## Generating scenarios
To generate scenarios you need to have `nix` installed on your machine.
After that, update `scenarios.yaml` to set endpoint and query parameters you want to test.
Start development server (connected to local postgres DB)
Run `./generate_scenarios.sh` and verify scenario responses looks correct.
17 changes: 17 additions & 0 deletions fly-app/bin/create_db_dump.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

if [ -z "$1" ]; then
echo "Usage: $0 <database_url>"
exit 1
fi

pg_dump --inserts --column-inserts -f dump.sql \
--exclude-table='deploys*' \
--exclude-table='events' \
--exclude-table='publishes*' \
--exclude-table='raw_events_v2' \
--exclude-table='registries' \
--exclude-table='test' \
--exclude-table='v2_*' \
--exclude-table='v4_*' \
"$1"
1 change: 1 addition & 0 deletions fly-app/bin/docker-init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -f dump.sql
3 changes: 3 additions & 0 deletions fly-app/bin/generate_scenarios.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
cd scenarios_generator
nix --extra-experimental-features nix-command --extra-experimental-features flakes run > ../src/generated.rs
14 changes: 14 additions & 0 deletions fly-app/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
services:
db:
image: postgres:17-alpine
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=postgres
ports:
- "5432:5432"
volumes:
# Maps the dump file to the auto-initialization directory.
# Note: Using dump.sql as generated by bin/create_db_dump.sh
- ./sql:/docker-entrypoint-initdb.d
27 changes: 27 additions & 0 deletions fly-app/scenarios_generator/flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions fly-app/scenarios_generator/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
description = "A flake to run the scenario URL generator";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};

outputs = { self, nixpkgs }:
let
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
pkgsFor = system: nixpkgs.legacyPackages.${system};
in
{
devShells = forAllSystems (system: {
default = (pkgsFor system).mkShell {
buildInputs = [
((pkgsFor system).python3.withPackages (ps: [ ps.pyyaml ps.requests ]))
];
};
});

apps = forAllSystems (system: {
default = {
type = "app";
program = let
pkgs = pkgsFor system;
pythonEnv = pkgs.python3.withPackages (ps: [ ps.pyyaml ps.requests ]);
in "${pkgs.writeShellScriptBin "generate-urls" ''
exec ${pythonEnv}/bin/python3 ${self}/generate_urls.py
''}/bin/generate-urls";
};
});
};
}
70 changes: 70 additions & 0 deletions fly-app/scenarios_generator/generate_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import yaml
import os
import requests
import json
from urllib.parse import urlencode

def main():
base_url = "http://localhost:8080"
script_dir = os.path.dirname(os.path.abspath(__file__))
yaml_path = os.path.join(script_dir, "scenarios.yaml")

with open(yaml_path, 'r') as f:
data = yaml.safe_load(f)

scenarios = data.get('scenarios', {})

# Print the requested header
print("// this code was generated by ./bin/generate_scenarios.sh")
print("#[cfg(test)]")
print("mod tests {")
print(" use crate::test::test_get;")
print()

for name, value in scenarios.items():
if isinstance(value, str):
path = value
elif isinstance(value, dict):
url = value.get('url', '')
params = {k: v for k, v in value.items() if k != 'url'}
if params:
query_string = urlencode(params)
path = f"{url}?{query_string}"
else:
path = url
else:
continue

if not path.startswith('/'):
path = '/' + path

full_url = f"{base_url}{path}"

try:
response = requests.get(full_url)
response.raise_for_status()
response_json = response.json()
pretty_json = json.dumps(response_json, indent=2)
# Indent the JSON (8 spaces for the content inside r#")
indented_json = "\n".join([f" {line}" for line in pretty_json.splitlines()])
except Exception as e:
indented_json = f" // Error fetching data: {e}"

template = f""" #[actix_web::test]
async fn test_{name}_get() {{
test_get(
"{path}",
r#"
{indented_json}
"#,
)
.await;
}}"""
print(template)
print()

# Close the mod tests block
print("}")

if __name__ == "__main__":
main()
39 changes: 39 additions & 0 deletions fly-app/scenarios_generator/scenarios.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
scenarios:
index: "/"
v1: "/v1"
wasms_unlimited:
url: "/v1/wasms"
wasms_limit:
url: "/v1/wasms"
limit: 2
wasms_limit_and_cursor:
url: "/v1/wasms"
limit: 2
cursor: "1673850-e2a17207280983bdab606afa65fcd52fa8eaeea6dfd5be212de62f2b567390a8-op-0-event-1"
wasm_main:
url: "/v1/wasms/oz-ft-allowlist-capped-pausable"
wasm_main_versioned:
url: "/v1/wasms/oz-ft-allowlist-capped-pausable/v/0.6.0"
wasm_unverified:
url: "/v1/wasms/unverified/guess-the-number"
wasm_unverified_versioned:
url: "/v1/wasms/unverified/guess-the-number/v/1.0.0"
contracts_unlimited:
url: "/v1/contracts"
contract:
url: "/v1/contracts/registry"
contracts_pagination_advanced_1:
url: "/v1/contracts"
limit: 1
contracts_pagination_advanced_2:
url: "/v1/contracts"
limit: 1
cursor: "1589244-0b3949bc352607c761fe12a0591d23f454303ba22973b62e4e12b60709cf9063-op-0-event-3"
contracts_pagination_advanced_3:
url: "/v1/contracts"
limit: 1
cursor: "1589244-0b3949bc352607c761fe12a0591d23f454303ba22973b62e4e12b60709cf9063-op-0-event-4"
contracts_pagination_advanced_4:
url: "/v1/contracts"
limit: 1
cursor: "1589244-0b3949bc352607c761fe12a0591d23f454303ba22973b62e4e12b60709cf9063-op-0-event-5"
1 change: 1 addition & 0 deletions fly-app/sql/1_role.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE ROLE neondb_owner;
Loading
Loading