ArtCraft Desktop (fresh start)

This is a fresh start for the `artcraft` repo.

The old monorepo, which included our web API gateway, job services, SRE
tools, various frontends, and more has moved to `artcraft-services`

You can find the full git history here:

https://github.com/storytold/artcraft-services

This change was motivated by the fact that the entire git history was
hundreds of gigabytes in size, which is unwieldy for anyone not in the
core team that doesn't care about support services outside of the core
artcraft app.

We wanted to keep this repo in its well-known place since we already
have users and activity here.

Please update your remotes to either `artcraft-services` or make a fresh
clone of this repo.

History can be found at the artcraft-services repo.
This commit is contained in:
Brandon Thomas
2026-09-11 14:19:51 -04:00
commit 0004726a36
5677 changed files with 520050 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
#!/usr/bin/env python3
"""
Bump the ArtCraft desktop app version across all three version files.
Usage:
python bump_artcraft_desktop_version.py # auto-bump minor (0.9.x -> 0.10.0)
python bump_artcraft_desktop_version.py 1.2.3 # set explicit version
The auto-bump reads the highest current version found across all three files,
increments the minor component by 1, and resets the patch to 0.
e.g. 0.9.4 -> 0.10.0, 0.22.3 -> 0.23.0
"""
import re
import sys
import json
import os
REPO_ROOT = os.path.join(os.path.dirname(__file__), "..", "..")
VERSION_RS = os.path.join(REPO_ROOT, "crates/desktop/artcraft/src/version.rs")
TAURI_CONF = os.path.join(REPO_ROOT, "crates/desktop/artcraft/tauri.conf.json")
TAURI_MAC = os.path.join(REPO_ROOT, "crates/desktop/artcraft/tauri-mac.conf.json")
VERSION_RE = re.compile(r"\d+\.\d+\.\d+")
def read_version_rs(path):
with open(path) as f:
content = f.read()
m = re.search(r'ARTCRAFT_VERSION:\s*&str\s*=\s*"(\d+\.\d+\.\d+)"', content)
if not m:
return None
return m.group(1)
def read_json_version(path):
with open(path) as f:
data = json.load(f)
v = data.get("version")
if v and VERSION_RE.fullmatch(v):
return v
return None
def bump_minor(version):
major, minor, _patch = version.split(".")
return f"{major}.{int(minor) + 1}.0"
def write_version_rs(path, new_version):
with open(path) as f:
content = f.read()
updated = re.sub(
r'(ARTCRAFT_VERSION:\s*&str\s*=\s*)"(\d+\.\d+\.\d+)"',
rf'\g<1>"{new_version}"',
content,
)
if updated == content:
raise ValueError(f"Could not find ARTCRAFT_VERSION in {path}")
with open(path, "w") as f:
f.write(updated)
def write_json_version(path, new_version):
with open(path) as f:
content = f.read()
updated = re.sub(
r'("version"\s*:\s*)"(\d+\.\d+\.\d+)"',
rf'\g<1>"{new_version}"',
content,
)
if updated == content:
raise ValueError(f"Could not find version field in {path}")
with open(path, "w") as f:
f.write(updated)
def parse_tuple(version):
return tuple(int(x) for x in version.split("."))
def main():
# --- Determine new version ---
if len(sys.argv) > 2:
print("Usage: bump_artcraft_desktop_version.py [VERSION]", file=sys.stderr)
sys.exit(1)
if len(sys.argv) == 2:
arg = sys.argv[1]
if not re.fullmatch(r"\d+\.\d+\.\d+", arg):
print(f"Error: version argument '{arg}' does not match \\d+\\.\\d+\\.\\d+", file=sys.stderr)
sys.exit(1)
new_version = arg
print(f"Using explicit version: {new_version}")
else:
# Read all three and take the highest
versions = {}
for label, reader, path in [
("version.rs", read_version_rs, VERSION_RS),
("tauri.conf.json", read_json_version, TAURI_CONF),
("tauri-mac.conf.json",read_json_version, TAURI_MAC),
]:
try:
v = reader(path)
if v:
versions[label] = v
print(f" {label}: {v}")
else:
print(f" {label}: (could not parse version)")
except Exception as e:
print(f" {label}: (error reading: {e})")
if not versions:
print("Error: could not read version from any file. Supply a version argument.", file=sys.stderr)
sys.exit(1)
highest = max(versions.values(), key=parse_tuple)
new_version = bump_minor(highest)
print(f"Highest current version: {highest} -> bumped to: {new_version}")
# --- Write new version to all three files ---
errors = []
for label, writer, path in [
("version.rs", write_version_rs, VERSION_RS),
("tauri.conf.json", write_json_version, TAURI_CONF),
("tauri-mac.conf.json",write_json_version, TAURI_MAC),
]:
try:
writer(path, new_version)
print(f" Updated {label}")
except Exception as e:
errors.append(f" Failed to update {label}: {e}")
if errors:
for err in errors:
print(err, file=sys.stderr)
sys.exit(1)
print(f"\nDone. All files set to {new_version}")
if __name__ == "__main__":
main()
+8
View File
@@ -0,0 +1,8 @@
#!/bin/bash
# NB: This only works on Mac, not Linux.
rm ~/Library/Caches/ai.artcraft.app/.cookies
rm -r ~/Library/Caches/artcraft/
rm -r ~/Library/Caches/ai.artcraft.app/
rm -r ~/Library/Caches/tauri-artcraft/
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
set -euxo pipefail
declare -r RELEASE_BRANCH="artcraft-release"
if git show-ref --verify --quiet "refs/heads/${RELEASE_BRANCH}"; then
git branch -D artcraft-release
fi
git checkout main
git pull
git checkout -b "${RELEASE_BRANCH}"
git push origin "${RELEASE_BRANCH}"
git checkout main
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# This works on Linux and MacOS to build production Artcraft
set -euxo pipefail
echo "Building production Artcraft..."
echo ""
root_dir=$(pwd)
frontend_path="${root_dir}/frontend"
rust_crate_path="${root_dir}/crates/desktop/artcraft"
# Build with the desktop app configuration.
config_path="${rust_crate_path}/tauri.conf.json"
pushd "${frontend_path}" || exit
npm install --verbose
popd || exit
export TAURI_FRONTEND_PATH="${frontend_path}"
export TAURI_APP_PATH="${rust_crate_path}"
# NB: The "frontend dev" script sets "production" too, so this must only control the
# hostnames we use, not minification, etc.
export VITE_ENVIRONMENT_TYPE="production"
export SQLX_OFFLINE=true
# This appears to trigger "nx build" instead of "nx dev".
cargo tauri build --config "${config_path}"
echo "Done!"
date "+Finished on %A, %B %e - %H:%M:%S (local timezone)"
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# This works on Linux and MacOS to launch the frontend dev server
root_dir=$(pwd)
frontend_path="${root_dir}/frontend"
source "${root_dir}/script/common/frontend_preflight.sh"
frontend_preflight "${frontend_path}"
echo "Running Artcraft Frontend in Dev Mode..."
echo ""
echo "You'll need to launch the Rust dev server as a second script!"
echo ""
# Kill any process running on port 5741, which will block startup
if lsof -i tcp:5173 &>/dev/null; then
lsof -i tcp:5173 -t | xargs kill -9
echo "Killed process running on port 5173"
else
echo "No process running on port 5173"
fi
pushd "${frontend_path}" || exit
frontend_npm_install
export VITE_ENVIRONMENT_TYPE="production"
nx dev artcraft
popd || exit
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# This works on Linux and MacOS to launch the frontend dev server
root_dir=$(pwd)
frontend_path="${root_dir}/frontend"
echo "Running Artcraft Frontend Build..."
echo ""
pushd "${frontend_path}" || exit
npm install --verbose
export VITE_ENVIRONMENT_TYPE="production"
nx build artcraft
popd || exit
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# This works on Linux and MacOS to launch the frontend dev server
root_dir=$(pwd)
frontend_path="${root_dir}/frontend"
echo "Running Artcraft Frontend in Production Build + Preview Mode... (It won't hot reload!)"
echo ""
echo "You'll need to launch the Rust dev server as a second script!"
echo ""
# Kill any process running on port 5741, which will block startup
if lsof -i tcp:5173 &>/dev/null; then
lsof -i tcp:5173 -t | xargs kill -9
echo "Killed process running on port 5173"
else
echo "No process running on port 5173"
fi
pushd "${frontend_path}" || exit
npm install --verbose
export VITE_ENVIRONMENT_TYPE="production"
nx production-preview artcraft
popd || exit
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# This works on Linux and MacOS to launch the Rust dev server
set -euxo pipefail
echo "Running Artcraft Rust in Dev Mode..."
echo ""
echo "You'll need to launch the frontend dev server as a second script!"
echo ""
root_dir=$(pwd)
frontend_path="${root_dir}/frontend"
rust_crate_path="${root_dir}/crates/desktop/artcraft"
sqlite_db_file="/tmp/tasks.sqlite"
# The tauri dev server integration is super annoying: It eats ctrl-c interrupts,
# it decoheres the and corrupts terminal output, and it's slow. This configuration
# allows us to start without it. Simply launch `nx` and the dev server as a separate
# process and leave tauri out of the loop
config_path="${rust_crate_path}/tauri-dev-hot-reload.conf.json"
export TAURI_FRONTEND_PATH="${frontend_path}"
export TAURI_APP_PATH="${rust_crate_path}"
echo "Create database file..."
touch "${sqlite_db_file}"
sqlx_migrate() {
echo "SQLx migrate database file..."
sqlx migrate run \
--database-url "sqlite:${sqlite_db_file}" \
--source "${root_dir}/_database/sql/artcraft_migrations"
export DATABASE_URL="sqlite:${sqlite_db_file}"
}
sqlx_offline() {
echo "SQLx offline..."
export SQLX_OFFLINE=true
}
# NB: Switch this for actively developing queries.
#sqlx_migrate
sqlx_offline
# Issue with Linux performance
# https://github.com/tauri-apps/tauri/issues/13498
export WEBKIT_DISABLE_DMABUF_RENDERER=1
export WEBKIT_DISABLE_COMPOSITING_MODE=1
echo "Build and run..."
RUSTFLAGS="-Awarnings" cargo tauri dev \
--verbose \
--no-dev-server \
--no-dev-server-wait \
--no-watch \
--config "${config_path}"
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# This works on Linux and MacOS to launch the Rust dev server
set -euxo pipefail
echo "Running Artcraft Rust in Dev Mode..."
echo ""
echo "You'll need to launch the frontend dev server as a second script!"
echo ""
root_dir=$(pwd)
frontend_path="${root_dir}/frontend"
rust_crate_path="${root_dir}/crates/desktop/artcraft"
sqlite_db_file="/tmp/tasks.sqlite"
# The tauri dev server integration is super annoying: It eats ctrl-c interrupts,
# it decoheres the and corrupts terminal output, and it's slow. This configuration
# allows us to start without it. Simply launch `nx` and the dev server as a separate
# process and leave tauri out of the loop
config_path="${rust_crate_path}/tauri-dev-static.conf.json"
export TAURI_FRONTEND_PATH="${frontend_path}"
export TAURI_APP_PATH="${rust_crate_path}"
echo "Create database file..."
touch "${sqlite_db_file}"
sqlx_migrate() {
echo "SQLx migrate database file..."
sqlx migrate run \
--database-url "sqlite:${sqlite_db_file}" \
--source "${root_dir}/_database/sql/artcraft_migrations"
export DATABASE_URL="sqlite:${sqlite_db_file}"
}
sqlx_offline() {
echo "SQLx offline..."
export SQLX_OFFLINE=true
}
# NB: Switch this for actively developing queries.
#sqlx_migrate
sqlx_offline
# Issue with Linux performance
# https://github.com/tauri-apps/tauri/issues/13498
export WEBKIT_DISABLE_DMABUF_RENDERER=1
export WEBKIT_DISABLE_COMPOSITING_MODE=1
echo "Build and run..."
RUSTFLAGS="-Awarnings" cargo tauri dev \
--no-dev-server \
--no-dev-server-wait \
--no-watch \
--config "${config_path}"
+37
View File
@@ -0,0 +1,37 @@
# Build Production Artcraft
Write-Host "Building production Artcraft..."
Write-Host ""
try
{
Push-Location -Path ".\frontend"
Write-Host "Installing latest dependencies..."
Write-Host ""
Write-Host "You may need to run ./clean_modules.sh or manually clean up occasionally!" -ForegroundColor red -BackgroundColor white
Write-Host ""
npm install --verbose
}
finally
{
Pop-Location
}
$env:VITE_ENVIRONMENT_TYPE="production"
$env:SQLX_OFFLINE="true"
# This tells Tauri *which* frontend and *which* Rust app to use since we're in a monorepo with several apps.
$env:TAURI_FRONTEND_PATH=".\frontend"
$env:TAURI_APP_PATH=".\crates\desktop\artcraft"
# The config file tells Tauri more instructions for the frontend build.
cargo tauri build --config ".\crates\desktop\artcraft\tauri.conf.json"
Write-Host ""
Write-Host "Production Build Done!" -ForegroundColor green -BackgroundColor white
Write-Host ""
Write-Host "You can find the installer in: target\release\bundle\nsis\ArtCraft_(version_info)-setup.exe"
Start-Process "explorer.exe" -ArgumentList ".\target\release\bundle\nsis"
+31
View File
@@ -0,0 +1,31 @@
# This runs Artcraft Frontend in dev mode on Windows
Write-Host "Running Artcraft Frontend in Dev Mode..."
Write-Host ""
Write-Host "You'll need to launch the Rust dev server as a second script!" -ForegroundColor red -BackgroundColor white
Write-Host ""
Push-Location -Path ".\frontend"
$env:VITE_ENVIRONMENT_TYPE="production"
try
{
Write-Host "Installing latest dependencies..."
Write-Host ""
Write-Host "You may need to run ./clean_modules.sh or manually clean up occasionally!" -ForegroundColor red -BackgroundColor white
Write-Host ""
npm install --verbose
Write-Host "Running dev server..."
Write-Host ""
Write-Host "If this isn't running on port 5173, you may need to kill a zombie process!" -ForegroundColor red -BackgroundColor white
Write-Host ""
npx nx dev artcraft
}
finally
{
Pop-Location
}
+16
View File
@@ -0,0 +1,16 @@
# This runs Artcraft Rust in dev mode on Windows
Write-Host "Running Artcraft Rust in Dev Mode..."
Write-Host ""
Write-Host "You'll need to launch the frontend dev server as a second script!" -ForegroundColor red -BackgroundColor white
Write-Host ""
# This tells Tauri *which* frontend and *which* Rust app to use since we're in a monorepo with several apps.
$env:TAURI_FRONTEND_PATH=".\frontend"
$env:TAURI_APP_PATH=".\crates\desktop\artcraft"
# Put SQLx into offline mode (no DB hits / migrations).
$env:SQLX_OFFLINE = "true"
# The config file tells Tauri more instructions for the frontend build.
cargo tauri dev --config ".\crates\desktop\artcraft\tauri-dev-hot-reload.conf.json"
+86
View File
@@ -0,0 +1,86 @@
#!/usr/bin/env bash
# Shared preflight checks for the frontend dev/build scripts.
#
# Usage (from a script that has set ${frontend_path}):
#
# source "${root_dir}/script/common/frontend_preflight.sh"
# frontend_preflight "${frontend_path}"
# ...
# pushd "${frontend_path}"
# frontend_npm_install
#
# Node 20+ is required by Nx 21 and comfortably covers Vite 6.
FRONTEND_MINIMUM_NODE_MAJOR=20
frontend_preflight() {
local frontend_path="$1"
if [ ! -d "${frontend_path}" ]; then
echo "ERROR: frontend directory not found at: ${frontend_path}"
echo "Run this script from the repository root."
exit 1
fi
# --- Node and npm must be installed ---
if ! command -v node &>/dev/null; then
echo "ERROR: node is not installed (or not on PATH)."
echo "Install Node.js ${FRONTEND_MINIMUM_NODE_MAJOR}+ via nvm (https://github.com/nvm-sh/nvm),"
echo "https://nodejs.org, or:"
echo " brew install node"
exit 1
fi
if ! command -v npm &>/dev/null; then
echo "ERROR: npm is not installed (or not on PATH). It normally ships with Node.js."
echo "Reinstall Node.js to get it back."
exit 1
fi
# --- Node must be recent enough for Nx 21 / Vite 6 ---
local node_major
node_major=$(node --version | sed -E 's/^v([0-9]+).*/\1/')
if [ "${node_major}" -lt "${FRONTEND_MINIMUM_NODE_MAJOR}" ]; then
echo "ERROR: Node.js ${FRONTEND_MINIMUM_NODE_MAJOR}+ is required (found $(node --version))."
echo "Upgrade via nvm ('nvm install --lts') or https://nodejs.org."
exit 1
fi
# --- The frontend uses npm; stale pnpm state breaks installs ---
# pnpm was briefly adopted ("add pnpm to solve build issues") and then dropped
# ("fix(frontend): consume video-editor libs via nx path aliases, drop pnpm").
# A node_modules tree written by pnpm makes npm fail with ENOTEMPTY errors.
if [ -e "${frontend_path}/pnpm-lock.yaml" ] \
|| [ -e "${frontend_path}/pnpm-workspace.yaml" ] \
|| [ -d "${frontend_path}/node_modules/.pnpm" ]; then
echo "ERROR: Stale pnpm artifacts detected in ${frontend_path}."
echo "The frontend uses npm (pnpm was dropped; see frontend/README.md)."
echo "Clean up with:"
echo " cd ${frontend_path} && rm -rf node_modules pnpm-lock.yaml pnpm-workspace.yaml && npm install"
exit 1
fi
}
# Run `npm install` in the current directory. If it fails (typically from a
# corrupted node_modules tree, eg. an interrupted install or a leftover pnpm
# layout causing ENOTEMPTY rename errors), wipe node_modules and the nx cache
# and retry once before giving up.
frontend_npm_install() {
if npm install; then
return 0
fi
echo ""
echo "WARNING: npm install failed. node_modules may be corrupted (eg. an"
echo "interrupted install or a mixed npm/pnpm tree). Wiping and retrying..."
echo ""
rm -rf node_modules .nx
if ! npm install; then
echo ""
echo "ERROR: npm install failed again. See the npm output above and the"
echo "troubleshooting section in frontend/README.md."
exit 1
fi
}
+105
View File
@@ -0,0 +1,105 @@
#!/bin/bash
declare -r entropy=$(xxd -l16 -ps /dev/urandom)
#declare -r CHROME_DIR="${HOME}/.chromeDevTemp"
declare -r chrome_dir="/tmp/chrome/${entropy}"
# See flags available and documentation:
# https://chromium.googlesource.com/chromium/src/+/HEAD/chrome/common/chrome_switches.cc
# https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
# https://peter.sh/experiments/chromium-command-line-switches/
# Seed the profile with DevTools preferences before Chrome starts.
# This sets: dock position = bottom, default panel = network.
# Chrome stores these in <user-data-dir>/Default/Preferences.
seed_devtools_preferences() {
local prefs='{"devtools":{"preferences":{"currentDockState":"\"bottom\"","panel-selected-tab":"\"network\""}}}'
# Seed both Default and Guest Profile — Chrome uses Guest Profile when
# launched with --guest, and Default otherwise.
for profile_name in "Default" "Guest Profile"; do
local prefs_dir="${chrome_dir}/${profile_name}"
mkdir -p "${prefs_dir}"
echo "${prefs}" > "${prefs_dir}/Preferences"
done
}
# TODO(bt): Math to determine better window placement.
# Flags reference:
# --auto-open-devtools-for-tabs Open DevTools automatically for every tab on launch.
# Dock position and default panel are set via seeded
# preferences (see seed_devtools_preferences above).
# --allow-running-insecure-content Allow HTTPS pages to load HTTP resources (mixed content).
# --disable-features=ChromeLabs, Disable Chrome Labs experiments UI and the
# DefaultBrowserPrompt feature-flag-based default browser prompt.
# --disable-site-isolation-trials Disable site isolation (allows cross-origin iframes
# to share process, useful for local dev).
# --disable-web-security Disable same-origin policy. Required for local dev
# where the frontend talks to a different-origin API.
# --ignore-certificate-errors Accept self-signed / invalid TLS certs.
# --no-default-browser-check Skip the "set as default browser" check on startup.
# --no-first-run Suppress the "Welcome to Google Chrome" first-run
# dialog (default browser checkbox, crash reporting, etc.).
# --install-autogenerated-theme Set a custom window color so the dev browser is
# visually distinct from your normal Chrome.
# --unsafely-treat-insecure-origin-as-secure
# Treat the given HTTP origin as secure. Required for
# APIs like getUserMedia() / navigator.mediaDevices
# which need a "secure context".
# --user-data-dir Use a throwaway profile directory so dev sessions
# don't pollute your real Chrome profile.
# --guest (Mac only) Launch in guest mode — no Google login screen.
# --window-position / --window-size Place the dev window predictably on screen.
launch_linux() {
seed_devtools_preferences
chromium \
--auto-open-devtools-for-tabs \
--allow-running-insecure-content \
--disable-features=ChromeLabs,DefaultBrowserPrompt \
--disable-site-isolation-trials \
--disable-web-security \
--ignore-certificate-errors \
--no-default-browser-check \
--no-first-run \
--install-autogenerated-theme="100,150,255" \
--unsafely-treat-insecure-origin-as-secure="http://localhost:5173" \
--user-data-dir="${chrome_dir}" \
--window-position=1200,300 \
--window-size=1500,1700 \
http://localhost:5173
}
launch_mac() {
seed_devtools_preferences
open -na "Google Chrome" --args \
--auto-open-devtools-for-tabs \
--disable-features=ChromeLabs,DefaultBrowserPrompt \
--disable-site-isolation-trials \
--disable-web-security \
--ignore-certificate-errors \
--no-default-browser-check \
--no-first-run \
--install-autogenerated-theme="100,150,255" \
--unsafely-treat-insecure-origin-as-secure="http://localhost:5173" \
--user-data-dir="${chrome_dir}" \
--window-position=1200,300 \
--window-size=1500,1700 \
--guest \
http://localhost:5173
}
case $OSTYPE in
linux*)
launch_linux
;;
darwin*)
launch_mac
;;
*)
echo "Unknown OS"
;;
esac
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
set -euxo pipefail
echo 'Looking for unused dependencies'
# NB(bt,2025-05-26): Previous version was "cargo-udeps 0.1.48"
# https://github.com/est31/cargo-udeps
# https://stackoverflow.com/a/72082679
# Needs nightly to run
cargo +nightly udeps --all-targets
# TODO: Ask for user input before applying some automated heuristics
echo 'Done.'
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
set -euxo pipefail
echo 'Run cargo check...'
#RUSTFLAGS=-Awarnings cargo check
cargo check
echo 'Run lints...'
./execute_lints.sh
echo 'Run tests...'
./execute_tests.sh
echo 'All tests and lints passed successfully!'
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
set -euxo pipefail
echo 'Running lints...'
# TODO: 'fakeyou_client' is broken
# TODO: 'sqlite_queries' and 'aichatbot-sidecar' are broken due to sqlite
# newrelic excluded since we don't author it
# --no-deps prevents running on path dependencies within workspaces
cargo cranky \
--no-deps \
--workspace \
--exclude aichatbot-sidecar \
--exclude fakeyou_client \
--exclude sqlite_queries \
--exclude newrelic-telemetry
echo 'Lints passed.'
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
set -euxo pipefail
echo 'Running tests...'
# TODO: Fix 'fakeyou_client' and 'billing_component'
# TODO: Run 'sqlite_queries' and 'aichatbot-sidecar' after postgres migrations
cargo test \
--workspace \
--exclude aichatbot-sidecar \
--exclude billing_component \
--exclude fakeyou_client \
--exclude inference-job \
--exclude mysql_queries \
--exclude sqlite_queries
# Single broken tests
cargo test \
--package inference-job \
-- \
--skip util::audiowmark::tests::test_audiowmark \
--skip util::common_commands::audiowmark::tests::test_audiowmark
cargo test \
--package mysql_queries \
-- \
--skip queries::model_weights::tests
echo 'Tests passed.'
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
#
# Fast, safe cleanup of the cargo ./target directory.
#
# Why this script exists:
# - `rm -rf target` hangs on huge target dirs (millions of small files).
# - `rm target/prefix*` blows up the shell glob with too many completions.
#
# Strategy:
# - Resolve target dir relative to the repo root, then sanity-check we're
# actually inside it before touching anything.
# - Walk the tree with `find -delete` (a single in-process traversal that
# unlinks as it goes — much faster than spawning rm per file).
# - Stream progress to stdout every N entries so it's clear something is
# happening.
set -euo pipefail
# --- locate repo root and target dir -----------------------------------------
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd -- "$SCRIPT_DIR/../.." && pwd)"
TARGET_DIR="${1:-$REPO_ROOT/target}"
# --- safety checks -----------------------------------------------------------
if [[ ! -d "$TARGET_DIR" ]]; then
echo "target dir does not exist: $TARGET_DIR"
exit 0
fi
# Resolve to absolute path and refuse anything that doesn't end in /target.
TARGET_DIR="$(cd -- "$TARGET_DIR" && pwd)"
case "$TARGET_DIR" in
*/target) ;;
*)
echo "refusing to clean a path that doesn't end in /target: $TARGET_DIR"
exit 1
;;
esac
# Refuse paths suspiciously close to root.
if [[ "$TARGET_DIR" == "/target" || "${#TARGET_DIR}" -lt 12 ]]; then
echo "refusing to clean suspicious path: $TARGET_DIR"
exit 1
fi
echo "Cleaning: $TARGET_DIR"
START=$(date +%s)
# --- delete with progress ----------------------------------------------------
# `find -delete` removes files and (now-empty) directories during traversal.
# We pipe -print through awk to emit a progress line every 5000 entries.
# Note: -print fires before -delete for files, after for dirs — fine for progress.
COUNT=$(
find "$TARGET_DIR" -mindepth 1 -print -delete 2>/dev/null \
| awk -v start="$START" '
{
n++
if (n % 5000 == 0) {
elapsed = systime() - start
rate = (elapsed > 0) ? n / elapsed : n
printf " deleted %d entries (%.0f/s)\n", n, rate > "/dev/stderr"
}
}
END { print n }
'
)
ELAPSED=$(( $(date +%s) - START ))
echo "Done. Removed $COUNT entries in ${ELAPSED}s."
# Recreate empty target/ so cargo doesn't complain on next build.
mkdir -p "$TARGET_DIR"
+13
View File
@@ -0,0 +1,13 @@
# This script is a little rough
# Step 1
cargo sqlx migrate run \
--database-url "sqlite:C:\Users\Bombay\AppData\Local\Temp\tasks.sqlite" \
--source "C:\Users\Bombay\Documents\GitHub\storyteller-rust\_sql\artcraft_migrations"
# Step 2
Push-Location -Path ".\crates\schema\database\sqlite_tasks"
cargo sqlx prepare \
--database-url "sqlite:C:\Users\Bombay\AppData\Local\Temp\tasks.sqlite"
Pop-Location