Migrate to using taskfiles
This commit is contained in:
parent
0e1849061b
commit
6ea7d53a49
21 changed files with 564 additions and 391 deletions
7
.github/workflows/check.yml
vendored
7
.github/workflows/check.yml
vendored
|
|
@ -32,5 +32,10 @@ jobs:
|
|||
toolchain: "1.92.0"
|
||||
components: clippy, rustfmt
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
|
||||
- name: Lint & test
|
||||
run: scripts/check.sh
|
||||
run: task check
|
||||
|
|
|
|||
7
.github/workflows/deploy-docs.yml
vendored
7
.github/workflows/deploy-docs.yml
vendored
|
|
@ -34,11 +34,16 @@ jobs:
|
|||
node-version: "25.x"
|
||||
check-latest: true
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Build docs
|
||||
run: scripts/build-docs.sh
|
||||
run: task docs:check
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
|
|
|
|||
17
.github/workflows/e2e.yml
vendored
17
.github/workflows/e2e.yml
vendored
|
|
@ -37,12 +37,13 @@ jobs:
|
|||
toolchain: "1.92.0"
|
||||
components: clippy, rustfmt
|
||||
|
||||
- name: Setup rust
|
||||
run: |
|
||||
which sqlx || cargo install sqlx-cli
|
||||
cd sync-server
|
||||
sqlx database create --database-url sqlite://db.sqlite3
|
||||
sqlx migrate run --source src/app_state/database/migrations --database-url sqlite://db.sqlite3
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
|
||||
- name: Setup database
|
||||
run: task db:setup
|
||||
|
||||
- name: E2E tests
|
||||
run: |
|
||||
|
|
@ -51,7 +52,7 @@ jobs:
|
|||
SERVER_PID=$!
|
||||
cd ..
|
||||
|
||||
scripts/e2e.sh 8
|
||||
task e2e -- 8
|
||||
EXIT_CODE=$?
|
||||
|
||||
kill $SERVER_PID 2>/dev/null || true
|
||||
|
|
@ -69,4 +70,4 @@ jobs:
|
|||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: scripts/clean-up.sh
|
||||
run: task clean
|
||||
|
|
|
|||
18
.github/workflows/publish-plugin.yml
vendored
18
.github/workflows/publish-plugin.yml
vendored
|
|
@ -22,25 +22,27 @@ jobs:
|
|||
node-version: "25.x"
|
||||
check-latest: true
|
||||
|
||||
- name: Build plugin
|
||||
run: |
|
||||
cd frontend
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: "1.92.0"
|
||||
components: clippy, rustfmt
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
|
||||
- name: Install cross-compilation tools
|
||||
run: |
|
||||
apt update
|
||||
apt install -y gcc-aarch64-linux-gnu musl-tools gcc-mingw-w64-x86-64
|
||||
|
||||
- name: Build Linux and Windows binaries
|
||||
run: ./scripts/build-sync-server-binaries.sh
|
||||
- name: Build frontend
|
||||
run: task frontend:build
|
||||
|
||||
- name: Build binaries
|
||||
run: task release:build-binaries
|
||||
|
||||
- name: Create release
|
||||
env:
|
||||
|
|
|
|||
132
CLAUDE.md
132
CLAUDE.md
|
|
@ -49,8 +49,24 @@ The sync-client builds two separate bundles:
|
|||
|
||||
## Development Commands
|
||||
|
||||
This project uses [Taskfile](https://taskfile.dev/) for task automation. Run `task --list` to see all available tasks.
|
||||
|
||||
### Initial Setup
|
||||
|
||||
**Taskfile:**
|
||||
|
||||
```bash
|
||||
# Install Task (https://taskfile.dev/installation/)
|
||||
# macOS
|
||||
brew install go-task
|
||||
|
||||
# Linux
|
||||
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
|
||||
|
||||
# Or via npm
|
||||
npm install -g @go-task/cli
|
||||
```
|
||||
|
||||
**Node.js (requires version 25):**
|
||||
|
||||
```bash
|
||||
|
|
@ -71,60 +87,89 @@ cargo install sqlx-cli cargo-machete cargo-edit cargo-insta
|
|||
**Frontend:**
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
task frontend:install
|
||||
```
|
||||
|
||||
### Server Development
|
||||
### Common Tasks (Taskfile)
|
||||
|
||||
```bash
|
||||
task check # Full CI check (lint, test, format). Run before pushing.
|
||||
task check:fix # Same as above but auto-fixes issues
|
||||
task e2e -- 8 # E2E tests with 8 concurrent clients
|
||||
task clean # Clean logs and database files
|
||||
task update-api-types # Update TypeScript bindings from Rust types
|
||||
task release:bump -- patch # Bump version (patch|minor|major)
|
||||
```
|
||||
|
||||
### Server Tasks
|
||||
|
||||
```bash
|
||||
task rust:run # Start development server
|
||||
task rust:test # Run all Rust tests
|
||||
task rust:clippy # Lint Rust code
|
||||
task rust:clippy-fix # Auto-fix clippy warnings
|
||||
task rust:fmt # Format Rust code
|
||||
task rust:fmt-check # Check Rust formatting
|
||||
task rust:machete # Detect unused dependencies
|
||||
```
|
||||
|
||||
### Frontend Tasks
|
||||
|
||||
```bash
|
||||
task frontend:dev # Start development mode
|
||||
task frontend:build # Build all workspaces
|
||||
task frontend:test # Run all frontend tests
|
||||
task frontend:lint # Lint and format TypeScript
|
||||
```
|
||||
|
||||
### Database Tasks
|
||||
|
||||
```bash
|
||||
task db:setup # Create and migrate database
|
||||
task db:reset # Reset database (delete and recreate)
|
||||
task db:prepare # Prepare SQLx offline data
|
||||
task db:add-migration NAME=<migration_name> # Add new migration
|
||||
```
|
||||
|
||||
### Documentation Tasks
|
||||
|
||||
```bash
|
||||
task docs:check # Build and check documentation
|
||||
task docs:dev # Start documentation dev server
|
||||
```
|
||||
|
||||
### Direct Commands (Alternative)
|
||||
|
||||
If you prefer not to use Taskfile, these commands work directly:
|
||||
|
||||
**Server:**
|
||||
|
||||
```bash
|
||||
cd sync-server
|
||||
cargo run config-e2e.yml # Start development server
|
||||
cargo test --verbose # Run all Rust tests
|
||||
cargo test <test_name> # Run specific test
|
||||
cargo clippy --all-targets --all-features # Lint Rust code
|
||||
cargo clippy --all-targets --all-features --fix --allow-dirty --allow-staged # Auto-fix clippy warnings
|
||||
cargo fmt --all -- --check # Check Rust formatting
|
||||
cargo fmt --all # Auto-format Rust code
|
||||
cargo machete --with-metadata # Detect unused dependencies
|
||||
cargo clippy --all-targets --all-features # Lint
|
||||
cargo fmt --all # Format
|
||||
```
|
||||
|
||||
### Frontend Development
|
||||
**Frontend:**
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run dev # Start development mode (watches sync-client and obsidian-plugin)
|
||||
npm run dev # Development mode
|
||||
npm run build # Build all workspaces
|
||||
npm run build -w sync-client # Build specific workspace
|
||||
npm run test # Run all tests across all workspaces
|
||||
npm run test -w sync-client # Run tests for specific workspace
|
||||
npm run lint # Lint and format TypeScript code with ESLint + Prettier
|
||||
npm run test # Run tests
|
||||
npm run lint # Lint and format
|
||||
```
|
||||
|
||||
### Database Operations
|
||||
**Database:**
|
||||
|
||||
```bash
|
||||
cd sync-server
|
||||
# Create/reset database for development
|
||||
rm -rf db.sqlite*
|
||||
sqlx database create --database-url sqlite://db.sqlite3
|
||||
sqlx migrate run --source src/app_state/database/migrations --database-url sqlite://db.sqlite3
|
||||
cargo sqlx prepare --workspace
|
||||
|
||||
# Add new migration
|
||||
sqlx migrate add --source src/app_state/database/migrations <migration_name>
|
||||
sqlx migrate run --source src/app_state/database/migrations --database-url sqlite://db.sqlite3
|
||||
```
|
||||
|
||||
### Project Scripts
|
||||
|
||||
- `scripts/check.sh`: Full CI check (builds, lints, tests both server and frontend). **Run before pushing.**
|
||||
- `scripts/check.sh --fix`: Same as above but auto-fixes linting and formatting issues
|
||||
- `scripts/e2e.sh`: End-to-end testing (e.g., `scripts/e2e.sh 8` for 8 concurrent clients)
|
||||
- `scripts/clean-up.sh`: Clean logs and database files
|
||||
- `scripts/bump-version.sh patch`: Publish new version (options: patch, minor, major)
|
||||
- `scripts/update-api-types.sh`: Update TypeScript bindings from Rust types (uses ts-rs)
|
||||
|
||||
## Code Structure
|
||||
|
||||
### Workspace Configuration
|
||||
|
|
@ -141,7 +186,7 @@ The frontend uses npm workspaces with four packages:
|
|||
Rust structs generate TypeScript types via ts-rs crate:
|
||||
|
||||
1. Rust structs annotated with `#[derive(TS)]` export to `sync-server/bindings/`
|
||||
2. Run `scripts/update-api-types.sh` to copy bindings to `frontend/sync-client/src/services/types/`
|
||||
2. Run `task update-api-types` to copy bindings to `frontend/sync-client/src/services/types/`
|
||||
3. Frontend imports these types for type-safe API communication
|
||||
|
||||
### Important Implementation Details
|
||||
|
|
@ -156,25 +201,18 @@ Rust structs generate TypeScript types via ts-rs crate:
|
|||
|
||||
### Running Tests
|
||||
|
||||
**Server:**
|
||||
|
||||
```bash
|
||||
cargo test --verbose # All tests
|
||||
cargo test <test_name> # Specific test
|
||||
task rust:test # All Rust tests
|
||||
task frontend:test # All frontend tests
|
||||
task e2e -- 8 # E2E with 8 concurrent clients
|
||||
task clean # Clean up after tests
|
||||
```
|
||||
|
||||
**Frontend:**
|
||||
Or use direct commands:
|
||||
|
||||
```bash
|
||||
npm run test # All workspaces
|
||||
npm run test -w sync-client # Specific workspace
|
||||
```
|
||||
|
||||
**E2E:**
|
||||
|
||||
```bash
|
||||
scripts/e2e.sh 8 # 8 concurrent clients
|
||||
scripts/clean-up.sh # Clean up after tests
|
||||
cd sync-server && cargo test --verbose # Rust tests
|
||||
cd frontend && npm run test # Frontend tests
|
||||
```
|
||||
|
||||
### Test Structure
|
||||
|
|
|
|||
96
Taskfile.yml
Normal file
96
Taskfile.yml
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
version: "3"
|
||||
|
||||
vars:
|
||||
NODE_VERSION: "25"
|
||||
|
||||
includes:
|
||||
rust:
|
||||
taskfile: ./taskfiles/rust.yml
|
||||
dir: ./sync-server
|
||||
frontend:
|
||||
taskfile: ./taskfiles/frontend.yml
|
||||
dir: ./frontend
|
||||
db:
|
||||
taskfile: ./taskfiles/database.yml
|
||||
dir: ./sync-server
|
||||
e2e:
|
||||
taskfile: ./taskfiles/e2e.yml
|
||||
docs:
|
||||
taskfile: ./taskfiles/docs.yml
|
||||
dir: ./docs
|
||||
release:
|
||||
taskfile: ./taskfiles/release.yml
|
||||
|
||||
tasks:
|
||||
check:
|
||||
desc: Run all checks (lint, test, format)
|
||||
cmds:
|
||||
- task: check-node
|
||||
- task: db:setup
|
||||
- task: rust:test
|
||||
- task: rust:lint
|
||||
- task: update-api-types
|
||||
- task: frontend:install
|
||||
- task: frontend:build
|
||||
- task: frontend:test
|
||||
- task: frontend:lint
|
||||
- task: format
|
||||
- task: check-clean
|
||||
|
||||
check:fix:
|
||||
desc: Run all checks with auto-fix enabled
|
||||
cmds:
|
||||
- task: check-node
|
||||
- task: db:setup
|
||||
- task: rust:test
|
||||
- task: rust:lint-fix
|
||||
- task: update-api-types
|
||||
- task: frontend:install
|
||||
- task: frontend:build
|
||||
- task: frontend:test
|
||||
- task: frontend:lint
|
||||
- task: format
|
||||
|
||||
check-node:
|
||||
internal: true
|
||||
silent: true
|
||||
preconditions:
|
||||
- sh: node -v | grep -q "^v{{.NODE_VERSION}}"
|
||||
msg: "Node.js {{.NODE_VERSION}} required (found: $(node -v))"
|
||||
cmds:
|
||||
- echo "Node.js {{.NODE_VERSION}} confirmed"
|
||||
|
||||
check-clean:
|
||||
internal: true
|
||||
preconditions:
|
||||
- sh: test -z "$(git status --porcelain)"
|
||||
msg: |
|
||||
Working directory not clean after linting:
|
||||
$(git status --porcelain)
|
||||
|
||||
format:
|
||||
desc: Format all files with Prettier
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
cmds:
|
||||
- npx -C frontend prettier --write "**/*.{ts,js,json,md,yml,yaml}"
|
||||
|
||||
update-api-types:
|
||||
desc: Update TypeScript bindings from Rust types
|
||||
cmds:
|
||||
- rm -rf sync-server/bindings
|
||||
- task: rust:export-bindings
|
||||
- cp -r sync-server/bindings/* frontend/sync-client/src/services/types/
|
||||
- cd frontend && npm run lint
|
||||
- task: format
|
||||
|
||||
clean:
|
||||
desc: Clean up logs and databases
|
||||
cmds:
|
||||
- rm -rf sync-server/databases logs
|
||||
|
||||
e2e:
|
||||
desc: Run E2E tests (usage - task e2e -- 8)
|
||||
cmds:
|
||||
- task: e2e:run
|
||||
vars:
|
||||
PROCESS_COUNT: "{{.CLI_ARGS}}"
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
./scripts/utils/check-node.sh
|
||||
|
||||
cd docs
|
||||
|
||||
npm ci
|
||||
npm run format:check
|
||||
npm run spell:check
|
||||
npm run build
|
||||
|
||||
cd -
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/../sync-server"
|
||||
|
||||
# Setup database
|
||||
sqlx database create --database-url sqlite://db.sqlite3 2>/dev/null || true
|
||||
sqlx migrate run --source src/app_state/database/migrations --database-url sqlite://db.sqlite3
|
||||
|
||||
targets=${@:-"x86_64-unknown-linux-gnu x86_64-unknown-linux-musl aarch64-unknown-linux-gnu x86_64-pc-windows-gnu"}
|
||||
|
||||
mkdir -p artifacts
|
||||
rm -f artifacts/sync-server-*
|
||||
|
||||
|
||||
for target in $targets; do
|
||||
echo "Building $target..."
|
||||
|
||||
# Set linkers for cross-compilation
|
||||
case "$target" in
|
||||
aarch64-unknown-linux-gnu)
|
||||
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc ;;
|
||||
x86_64-unknown-linux-musl)
|
||||
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc ;;
|
||||
x86_64-pc-windows-gnu)
|
||||
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc ;;
|
||||
esac
|
||||
|
||||
rustup target add "$target" 2>/dev/null || true
|
||||
|
||||
cargo build --release --target "$target"
|
||||
ext=""
|
||||
[[ "$target" == *windows* ]] && ext=".exe"
|
||||
|
||||
name="sync-server-${target//-/_}$ext"
|
||||
name="${name//x86_64_unknown_linux_gnu/linux-x86_64}"
|
||||
name="${name//x86_64_unknown_linux_musl/linux-x86_64-musl}"
|
||||
name="${name//aarch64_unknown_linux_gnu/linux-aarch64}"
|
||||
name="${name//x86_64_pc_windows_gnu/windows-x86_64}"
|
||||
|
||||
cp "target/$target/release/sync_server$ext" "artifacts/$name"
|
||||
echo "✓ Built $name"
|
||||
done
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ -z $1 ]]; then
|
||||
echo "Usage: $0 {patch|minor|major}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $1 =~ ^(patch|minor|major)$ ]]; then
|
||||
echo "Creating a new '$1' version"
|
||||
else
|
||||
echo "Invalid argument: $1"
|
||||
echo "Usage: $0 {patch|minor|major}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cargo install cargo-edit --force
|
||||
|
||||
if [[ -n $(git status --porcelain) ]]; then
|
||||
echo "Your working directory is not clean. Please commit or stash your changes before proceeding."
|
||||
exit 1
|
||||
else
|
||||
echo "Your working directory is clean."
|
||||
fi
|
||||
|
||||
echo "Bumping sync-server versions"
|
||||
cd sync-server
|
||||
cargo set-version --bump $1
|
||||
|
||||
echo "Bumping frontend versions"
|
||||
cd ../frontend
|
||||
npm version $1 --workspaces
|
||||
cd ..
|
||||
|
||||
cp frontend/obsidian-plugin/manifest.json manifest.json # for BRAT, otherwise it wouldn't update
|
||||
|
||||
# Format all files across the project (frontend and backend)
|
||||
npx -C frontend prettier --write "**/*.{ts,js,json,md,yml,yaml}"
|
||||
|
||||
# Commit and tag
|
||||
git add .
|
||||
TAG=$(node -p "require('./frontend/obsidian-plugin/package.json').version")
|
||||
git commit -m "Bump versions to $TAG"
|
||||
|
||||
git push
|
||||
echo "Tagging $TAG"
|
||||
git tag -a $TAG -m "Release $TAG"
|
||||
git push origin $TAG
|
||||
echo "Done"
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
FIX_MODE=false
|
||||
if [[ "$1" == "--fix" ]]; then
|
||||
FIX_MODE=true
|
||||
echo "Running in fix mode - will automatically fix linting and formatting issues"
|
||||
fi
|
||||
|
||||
./scripts/utils/check-node.sh
|
||||
|
||||
echo "Running checks in sync-server"
|
||||
|
||||
cd sync-server
|
||||
which sqlx || cargo install sqlx-cli
|
||||
sqlx database create --database-url sqlite://db.sqlite3
|
||||
sqlx migrate run --source src/app_state/database/migrations --database-url sqlite://db.sqlite3
|
||||
|
||||
cargo test --verbose
|
||||
|
||||
if [[ "$FIX_MODE" == true ]]; then
|
||||
cargo clippy --all-targets --all-features --fix --allow-dirty --allow-staged
|
||||
cargo fmt --all
|
||||
else
|
||||
cargo clippy --all-targets --all-features
|
||||
cargo fmt --all -- --check
|
||||
fi
|
||||
|
||||
which cargo-machete || cargo install cargo-machete
|
||||
cargo machete --with-metadata
|
||||
|
||||
cd ..
|
||||
scripts/update-api-types.sh # this will dirty up the git state if not up-to-date
|
||||
|
||||
echo "Running checks in frontend"
|
||||
cd frontend
|
||||
|
||||
if [[ "$FIX_MODE" == true ]]; then
|
||||
npm install
|
||||
else
|
||||
npm ci
|
||||
fi
|
||||
|
||||
cd ..
|
||||
|
||||
cd frontend
|
||||
npm run build
|
||||
npm run test
|
||||
npm run lint
|
||||
cd ..
|
||||
|
||||
# Format all files across the project (frontend and backend)
|
||||
# Prettier respects .gitignore by default
|
||||
npx -C frontend prettier --write "**/*.{ts,js,json,md,yml,yaml}"
|
||||
|
||||
if [[ "$FIX_MODE" == false ]] && [[ $(git status --porcelain) ]]; then
|
||||
git status --porcelain
|
||||
echo "Failing CI because the working directory is not clean after linting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Success"
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -rf sync-server/databases
|
||||
rm -rf logs
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
NO_COLOR=1
|
||||
FORCE_COLOR=0
|
||||
|
||||
./scripts/utils/check-node.sh
|
||||
|
||||
# Check if the argument is provided
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 <number_of_processes>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the number of processes from the first argument
|
||||
process_count=$1
|
||||
|
||||
mkdir -p logs
|
||||
|
||||
cd frontend
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
../scripts/utils/wait-for-server.sh
|
||||
|
||||
pids=()
|
||||
for i in $(seq 1 $process_count); do
|
||||
# Create a named pipe for this process
|
||||
pipe="/tmp/vaultlink_pipe_$$_$i"
|
||||
mkfifo "$pipe"
|
||||
|
||||
# Start the node process writing to the pipe
|
||||
node test-client/dist/cli.js > "$pipe" 2>&1 &
|
||||
pid=$!
|
||||
pids+=($pid)
|
||||
echo "Started process $i with PID: $pid"
|
||||
|
||||
# Read from pipe, prefix with PID
|
||||
(sed "s/^/[PID $pid] /" < "$pipe" > "../logs/log_${i}.log"; rm "$pipe") &
|
||||
done
|
||||
|
||||
cd ..
|
||||
|
||||
print_failed_log() {
|
||||
for i in $(seq 1 $process_count); do
|
||||
if [ -n "${pids[$i-1]}" ] && ! kill -0 ${pids[$i-1]} 2>/dev/null; then
|
||||
# Get the exit code of the process
|
||||
wait ${pids[$i-1]}
|
||||
exit_code=$?
|
||||
|
||||
# Only consider non-zero exit codes as failures
|
||||
if [ $exit_code -ne 0 ]; then
|
||||
echo "----- Log for process ${pids[$i-1]} (log_${i}.log) -----"
|
||||
cat "$(pwd)/logs/log_${i}.log"
|
||||
echo "Process ${pids[$i-1]} failed with exit code $exit_code. Log file: $(pwd)/logs/log_${i}.log"
|
||||
return 0
|
||||
else
|
||||
echo "Process ${pids[$i-1]} completed successfully with exit code 0"
|
||||
# Mark this PID as processed by setting it to empty
|
||||
pids[$i-1]=""
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "Monitoring $process_count processes"
|
||||
|
||||
# Monitor processes
|
||||
while true; do
|
||||
if print_failed_log; then
|
||||
# Kill remaining processes
|
||||
for pid in "${pids[@]}"; do
|
||||
if [ -n "$pid" ]; then
|
||||
kill $pid 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if all processes have completed
|
||||
all_done=true
|
||||
for pid in "${pids[@]}"; do
|
||||
if [ -n "$pid" ] && kill -0 $pid 2>/dev/null; then
|
||||
all_done=false
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if $all_done; then
|
||||
echo "All processes completed successfully"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sleep 0.2
|
||||
done
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
rm -rf sync-server/bindings
|
||||
|
||||
cd sync-server
|
||||
cargo test export_bindings
|
||||
cd -
|
||||
|
||||
cp -r sync-server/bindings/* frontend/sync-client/src/services/types/
|
||||
|
||||
cd frontend
|
||||
npm run lint
|
||||
cd ..
|
||||
|
||||
# Format all files across the project (frontend and backend)
|
||||
npx -C frontend prettier --write "**/*.{ts,js,json,md,yml,yaml}"
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
TARGET_NODE_VERSION=25
|
||||
|
||||
node_version=$(node -v | sed 's/^v\([0-9]*\).*/\1/')
|
||||
if [ "$node_version" != "$TARGET_NODE_VERSION" ]; then
|
||||
echo "Error: This script requires Node.js version $TARGET_NODE_VERSION, found: $node_version"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SERVER_URL="http://localhost:3000"
|
||||
MAX_RETRIES=30
|
||||
RETRY_INTERVAL_IN_SECONDS=5
|
||||
|
||||
echo "Waiting for $SERVER_URL to become available..."
|
||||
count=0
|
||||
while [ $count -lt $MAX_RETRIES ]; do
|
||||
if curl -s -f -o /dev/null $SERVER_URL; then
|
||||
echo "$SERVER_URL is now available!"
|
||||
break
|
||||
fi
|
||||
echo "Attempt $(($count+1))/$MAX_RETRIES: $SERVER_URL not available yet, retrying in ${RETRY_INTERVAL_IN_SECONDS}s..."
|
||||
sleep $RETRY_INTERVAL_IN_SECONDS
|
||||
count=$(($count+1))
|
||||
done
|
||||
|
||||
if [ $count -eq $MAX_RETRIES ]; then
|
||||
echo "Error: $SERVER_URL did not become available after $MAX_RETRIES attempts."
|
||||
exit 1
|
||||
fi
|
||||
25
taskfiles/database.yml
Normal file
25
taskfiles/database.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
version: "3"
|
||||
|
||||
vars:
|
||||
DATABASE_URL: "sqlite://db.sqlite3"
|
||||
MIGRATIONS_PATH: "src/app_state/database/migrations"
|
||||
|
||||
tasks:
|
||||
setup:
|
||||
desc: Create and migrate database
|
||||
sources:
|
||||
- "{{.MIGRATIONS_PATH}}/**/*.sql"
|
||||
generates:
|
||||
- "db.sqlite3"
|
||||
cmds:
|
||||
- which sqlx || cargo install sqlx-cli
|
||||
- sqlx database create --database-url {{.DATABASE_URL}} 2>/dev/null || true
|
||||
- sqlx migrate run --source {{.MIGRATIONS_PATH}} --database-url {{.DATABASE_URL}}
|
||||
- cargo sqlx prepare --workspace
|
||||
|
||||
add-migration:
|
||||
desc: Add a new migration
|
||||
requires:
|
||||
vars: [NAME]
|
||||
cmds:
|
||||
- sqlx migrate add --source {{.MIGRATIONS_PATH}} {{.NAME}}
|
||||
35
taskfiles/docs.yml
Normal file
35
taskfiles/docs.yml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
version: "3"
|
||||
|
||||
tasks:
|
||||
install:
|
||||
desc: Install docs dependencies
|
||||
run: once
|
||||
cmds:
|
||||
- npm ci
|
||||
|
||||
build:
|
||||
desc: Build documentation
|
||||
deps: [install]
|
||||
cmds:
|
||||
- npm run build
|
||||
|
||||
lint:
|
||||
desc: Check formatting and spelling
|
||||
deps: [install]
|
||||
cmds:
|
||||
- npm run format:check
|
||||
- npm run spell:check
|
||||
|
||||
check:
|
||||
desc: Run all documentation checks
|
||||
cmds:
|
||||
- task: :check-node
|
||||
- task: install
|
||||
- task: lint
|
||||
- task: build
|
||||
|
||||
dev:
|
||||
desc: Start documentation dev server
|
||||
deps: [install]
|
||||
cmds:
|
||||
- npm run dev
|
||||
134
taskfiles/e2e.yml
Normal file
134
taskfiles/e2e.yml
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
version: "3"
|
||||
|
||||
vars:
|
||||
SERVER_URL: "http://localhost:3000"
|
||||
MAX_RETRIES: 30
|
||||
RETRY_INTERVAL: 5
|
||||
LOG_DIR: "{{.ROOT_DIR}}/logs"
|
||||
|
||||
tasks:
|
||||
run:
|
||||
desc: Run E2E tests with specified number of processes
|
||||
summary: |
|
||||
Runs multiple concurrent test clients against the sync server.
|
||||
Each client performs random file operations to test synchronization.
|
||||
|
||||
Usage: task e2e -- <process_count>
|
||||
Example: task e2e -- 8
|
||||
deps: [prepare]
|
||||
requires:
|
||||
vars: [PROCESS_COUNT]
|
||||
preconditions:
|
||||
- sh: test "{{.PROCESS_COUNT}}" -ge 1 2>/dev/null
|
||||
msg: "PROCESS_COUNT must be a positive integer (got: {{.PROCESS_COUNT}})"
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
env:
|
||||
NO_COLOR: "1"
|
||||
FORCE_COLOR: "0"
|
||||
cmds:
|
||||
- task: wait-for-server
|
||||
- task: setup-logs
|
||||
- defer: { task: cleanup-pipes }
|
||||
- task: spawn-clients
|
||||
|
||||
prepare:
|
||||
desc: Build frontend for E2E tests
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
cmds:
|
||||
- task: :check-node
|
||||
- task: :frontend:build
|
||||
|
||||
wait-for-server:
|
||||
desc: Wait for server to become available
|
||||
internal: true
|
||||
silent: true
|
||||
cmds:
|
||||
- for: { var: ATTEMPTS, split: "\n" }
|
||||
cmd: |
|
||||
if curl -s -f -o /dev/null {{.SERVER_URL}}; then
|
||||
echo "Server available at {{.SERVER_URL}}"
|
||||
exit 0
|
||||
fi
|
||||
echo "Attempt {{.ITEM}}/{{.MAX_RETRIES}}: waiting {{.RETRY_INTERVAL}}s..."
|
||||
sleep {{.RETRY_INTERVAL}}
|
||||
if [ "{{.ITEM}}" = "{{.MAX_RETRIES}}" ]; then
|
||||
echo "Error: Server not available after {{.MAX_RETRIES}} attempts"
|
||||
exit 1
|
||||
fi
|
||||
vars:
|
||||
ATTEMPTS:
|
||||
sh: seq 1 {{.MAX_RETRIES}}
|
||||
|
||||
setup-logs:
|
||||
internal: true
|
||||
status:
|
||||
- test -d {{.LOG_DIR}}
|
||||
cmds:
|
||||
- mkdir -p {{.LOG_DIR}}
|
||||
|
||||
cleanup-pipes:
|
||||
internal: true
|
||||
cmds:
|
||||
- rm -f /tmp/vaultlink_pipe_* 2>/dev/null || true
|
||||
|
||||
spawn-clients:
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}/frontend"
|
||||
set: [errexit, pipefail]
|
||||
cmds:
|
||||
- |
|
||||
pids=()
|
||||
|
||||
# Start all client processes
|
||||
for i in $(seq 1 {{.PROCESS_COUNT}}); do
|
||||
pipe="/tmp/vaultlink_pipe_$$_$i"
|
||||
mkfifo "$pipe"
|
||||
node test-client/dist/cli.js > "$pipe" 2>&1 &
|
||||
pid=$!
|
||||
pids+=($pid)
|
||||
echo "Started client $i (PID: $pid)"
|
||||
(sed "s/^/[PID $pid] /" < "$pipe" > "{{.LOG_DIR}}/log_${i}.log"; rm "$pipe") &
|
||||
done
|
||||
|
||||
echo "Monitoring {{.PROCESS_COUNT}} client processes..."
|
||||
|
||||
# Monitor loop
|
||||
while true; do
|
||||
# Check for failures
|
||||
for i in $(seq 1 {{.PROCESS_COUNT}}); do
|
||||
idx=$((i-1))
|
||||
pid=${pids[$idx]}
|
||||
[ -z "$pid" ] && continue
|
||||
|
||||
if ! kill -0 $pid 2>/dev/null; then
|
||||
wait $pid
|
||||
code=$?
|
||||
if [ $code -ne 0 ]; then
|
||||
echo "Client $i (PID $pid) failed with exit code $code"
|
||||
echo "===== Log: {{.LOG_DIR}}/log_${i}.log ====="
|
||||
cat "{{.LOG_DIR}}/log_${i}.log"
|
||||
# Kill remaining processes
|
||||
for p in "${pids[@]}"; do
|
||||
[ -n "$p" ] && kill $p 2>/dev/null || true
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
echo "Client $i (PID $pid) completed successfully"
|
||||
pids[$idx]=""
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if all done
|
||||
all_done=true
|
||||
for pid in "${pids[@]}"; do
|
||||
[ -n "$pid" ] && kill -0 $pid 2>/dev/null && all_done=false && break
|
||||
done
|
||||
|
||||
if $all_done; then
|
||||
echo "All {{.PROCESS_COUNT}} clients completed successfully"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sleep 0.2
|
||||
done
|
||||
41
taskfiles/frontend.yml
Normal file
41
taskfiles/frontend.yml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
version: "3"
|
||||
|
||||
tasks:
|
||||
install:
|
||||
desc: Install frontend dependencies
|
||||
run: once
|
||||
cmds:
|
||||
- npm ci
|
||||
|
||||
build:
|
||||
desc: Build all frontend workspaces
|
||||
deps: [install]
|
||||
cmds:
|
||||
- npm run build
|
||||
|
||||
test:
|
||||
desc: Run all frontend tests
|
||||
cmds:
|
||||
- npm run test
|
||||
|
||||
lint:
|
||||
desc: Lint and format TypeScript code
|
||||
cmds:
|
||||
- npm run lint
|
||||
|
||||
dev:
|
||||
desc: Start development mode
|
||||
cmds:
|
||||
- npm run dev
|
||||
|
||||
workspace:
|
||||
desc: Run npm script in specific workspace
|
||||
summary: |
|
||||
Run any npm script in a specific workspace.
|
||||
|
||||
Usage: task frontend:workspace WORKSPACE=<name> SCRIPT=<script>
|
||||
Example: task frontend:workspace WORKSPACE=sync-client SCRIPT=build
|
||||
requires:
|
||||
vars: [WORKSPACE, SCRIPT]
|
||||
cmds:
|
||||
- npm run {{.SCRIPT}} -w {{.WORKSPACE}}
|
||||
44
taskfiles/release.yml
Normal file
44
taskfiles/release.yml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
version: "3"
|
||||
|
||||
tasks:
|
||||
bump:
|
||||
desc: Bump version (usage - task release:bump -- patch|minor|major)
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
requires:
|
||||
vars:
|
||||
- name: CLI_ARGS
|
||||
enum: [patch, minor, major]
|
||||
preconditions:
|
||||
- sh: test -z "$(git status --porcelain)"
|
||||
msg: "Working directory not clean. Commit or stash changes first."
|
||||
vars:
|
||||
BUMP_TYPE: "{{.CLI_ARGS}}"
|
||||
cmds:
|
||||
- echo "Creating {{.BUMP_TYPE}} release..."
|
||||
- cd sync-server && cargo set-version --bump {{.BUMP_TYPE}}
|
||||
- cd frontend && npm version {{.BUMP_TYPE}} --workspaces
|
||||
- cp frontend/obsidian-plugin/manifest.json manifest.json
|
||||
- task: :format
|
||||
- |
|
||||
git add .
|
||||
TAG=$(node -p "require('./frontend/obsidian-plugin/package.json').version")
|
||||
git commit -m "Bump versions to $TAG"
|
||||
git push
|
||||
git tag -a $TAG -m "Release $TAG"
|
||||
git push origin $TAG
|
||||
echo "Released $TAG"
|
||||
|
||||
create-release:
|
||||
desc: Create GitHub release with all artifacts
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
cmds:
|
||||
- task: :db:setup
|
||||
- task: :frontend:build
|
||||
- task: :rust:build-binaries
|
||||
- |
|
||||
tag="${GITHUB_REF#refs/tags/}"
|
||||
mkdir -p release
|
||||
cp frontend/obsidian-plugin/dist/* release/
|
||||
cp sync-server/artifacts/sync-server-* release/
|
||||
cd release
|
||||
gh release create "$tag" --title="$tag" --draft *
|
||||
73
taskfiles/rust.yml
Normal file
73
taskfiles/rust.yml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
version: "3"
|
||||
|
||||
tasks:
|
||||
build:
|
||||
desc: Build sync-server
|
||||
cmds:
|
||||
- cargo build {{if .RELEASE}}--release{{end}}
|
||||
|
||||
test:
|
||||
desc: Run Rust tests
|
||||
cmds:
|
||||
- cargo test --verbose
|
||||
|
||||
lint:
|
||||
desc: Run all linters (clippy, fmt check, machete)
|
||||
cmds:
|
||||
- cargo fmt --all -- --check
|
||||
- cargo clippy --all-targets --all-features
|
||||
- cargo machete --with-metadata
|
||||
|
||||
lint-fix:
|
||||
desc: Auto-fix linting issues (fmt, clippy)
|
||||
cmds:
|
||||
- cargo fmt --all
|
||||
- cargo clippy --all-targets --all-features --fix --allow-dirty --allow-staged
|
||||
|
||||
run:
|
||||
desc: Run the sync server
|
||||
cmds:
|
||||
- cargo run {{.CONFIG | default "config-e2e.yml"}} {{if .NO_COLOR}}--color never{{end}}
|
||||
|
||||
export-bindings:
|
||||
desc: Export TypeScript bindings
|
||||
cmds:
|
||||
- cargo test export_bindings
|
||||
|
||||
build-binaries:
|
||||
desc: Build cross-platform release binaries
|
||||
summary: |
|
||||
Builds release binaries for multiple platforms.
|
||||
Default targets: linux-x86_64, linux-x86_64-musl, linux-aarch64, windows-x86_64
|
||||
|
||||
Override with: task rust:build-binaries TARGETS="x86_64-unknown-linux-gnu"
|
||||
vars:
|
||||
TARGETS: '{{.TARGETS | default "x86_64-unknown-linux-gnu x86_64-unknown-linux-musl aarch64-unknown-linux-gnu x86_64-pc-windows-gnu"}}'
|
||||
cmds:
|
||||
- mkdir -p artifacts
|
||||
- rm -f artifacts/sync-server-*
|
||||
- for: { var: TARGETS }
|
||||
task: build-target
|
||||
vars:
|
||||
TARGET: "{{.ITEM}}"
|
||||
|
||||
build-target:
|
||||
internal: true
|
||||
label: "build-{{.TARGET}}"
|
||||
vars:
|
||||
EXT: '{{if contains "windows" .TARGET}}.exe{{end}}'
|
||||
LINKER_VAR: >-
|
||||
{{if eq .TARGET "aarch64-unknown-linux-gnu"}}CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
|
||||
{{else if eq .TARGET "x86_64-unknown-linux-musl"}}CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc
|
||||
{{else if eq .TARGET "x86_64-pc-windows-gnu"}}CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
|
||||
{{end}}
|
||||
OUTPUT_NAME: >-
|
||||
{{.TARGET | replace "x86_64-unknown-linux-gnu" "linux-x86_64"
|
||||
| replace "x86_64-unknown-linux-musl" "linux-x86_64-musl"
|
||||
| replace "aarch64-unknown-linux-gnu" "linux-aarch64"
|
||||
| replace "x86_64-pc-windows-gnu" "windows-x86_64"}}
|
||||
cmds:
|
||||
- rustup target add {{.TARGET}} 2>/dev/null || true
|
||||
- '{{.LINKER_VAR}} cargo build --release --target {{.TARGET}}'
|
||||
- cp target/{{.TARGET}}/release/sync_server{{.EXT}} artifacts/sync-server-{{.OUTPUT_NAME}}{{.EXT}}
|
||||
- echo "Built sync-server-{{.OUTPUT_NAME}}{{.EXT}}"
|
||||
Loading…
Add table
Add a link
Reference in a new issue