Sonar: clear the shell, workflow, Rust and HTML findings (#2818)

Clears the open SonarCloud issues outside the TypeScript frontend,
except the Rust ones, which moved to #2823 so each PR stays small.
Compile and tests are left to CI.

**Security**
- `frontend/api_docs.html` (Web:S5725): `integrity` (sha384 of the
pinned `swagger-ui-dist@5.32.0` files) and `crossorigin="anonymous"` on
the three unpkg assets, over `https:`.
- S6505: `--ignore-scripts` on `npm install` / `npm ci` in the dev and
build scripts and in the macOS and Windows publish workflows.
`artcraft-linux-publish.yml` already builds with `npm ci
--ignore-scripts`, and the frontend has no install scripts of its own.
- S7637: `dtolnay/rust-toolchain@stable` and
`tauri-apps/tauri-action@v0` pinned by commit SHA. For tauri-action
that's the commit `v0` points to (`84b9d35…`). The Linux workflow had
pinned the tag object instead, and is fixed the same way.
- S6505 / S8543: the macOS build runs `./node_modules/.bin/nx` instead
of `npx nx`, as the Linux workflow does.

**Reliability**
- shell:S7688: `[[ ]]` in place of `[` / `test` in
`frontend_preflight.sh` and the Linux packaging scripts.

**Analysis scope** (`sonar-project.properties`), each with its reason in
the file:
- Not analysed: `crates/vendor/**` (third-party), the upstream Python
reference implementations beside the Grok and Sora clients (nothing runs
them), and the hand-run developer tools `frontend/scripts/unix-dev.mjs`
and `frontend/tools/performance/**`. These held the S8564, S1244, S2245,
S4036, S5443 and S8707 findings.
- rust:S4347 not raised on `DeterministicRng`, the fixed-seed generator
for tests.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Improvements**
* File downloads and database maintenance now use asynchronous
operations, helping the app remain responsive during these tasks.
  * API documentation assets load over HTTPS with integrity checks.
* **Build and Reliability**
* Build and publishing workflows use pinned tool versions and skip
package lifecycle scripts during dependency installation.
  * Linux packaging checks use consistent shell conditionals.
* Frontend builds use the locally installed Nx command where applicable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- typescript:S2187 not raised on the ApiManager tests, which build their
cases with shared helpers that call `it` (`BetaKeysApi.test.ts`).
typescript:S2819 not raised on `*.worker.ts`: a dedicated worker's
messages come only from the page that started it.
This commit is contained in:
Dylan M. Taylor authored and GitHub committed 2026-11-10 21:39:12 -05:00
1 parent 773e5925b9
commit 0c11395467
13 files changed
+52 -30

No files matched your search

+1 -1
View File
@@ -80,7 +80,7 @@ jobs:
working-directory: frontend
- run: ./node_modules/.bin/nx run artcraft:build
working-directory: frontend
- uses: tauri-apps/tauri-action@fce9c6108b31ea247710505d3aaaa893ee6768d4 # v0
- uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0
with:
projectPath: crates/desktop/artcraft
args: --target ${{ matrix.target }} --bundles ${{ matrix.bundles }} --config ${{ github.workspace }}/packaging/linux/tauri.conf.json
+5 -6
View File
@@ -46,7 +46,7 @@ jobs:
node-version: lts/*
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
with:
targets: ${{ matrix.platform == 'macos-latest-xlarge' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
@@ -72,7 +72,7 @@ jobs:
npm cache clean --force
echo "Installing all workspace dependencies..."
npm ci
npm ci --ignore-scripts
echo "=== Version Information ==="
echo "Node version:"
@@ -205,9 +205,8 @@ jobs:
# Increase Node.js memory limit for the build
export NODE_OPTIONS="--max-old-space-size=8192"
# Use npx to ensure we use the local nx version
echo "Building with npx nx..."
npx nx run artcraft:build
echo "Building with nx..."
./node_modules/.bin/nx run artcraft:build
echo "Checking build output..."
# shellcheck disable=SC2012
@@ -226,7 +225,7 @@ jobs:
- name: build and publish
uses: tauri-apps/tauri-action@v0
uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_ID: ${{ secrets.APPLE_ID }}
@@ -36,7 +36,7 @@ jobs:
- uses: actions/checkout@v7
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
- name: install wreq dependencies
run: |
@@ -61,7 +61,7 @@ jobs:
npm cache clean --force
echo "Installing all workspace dependencies..."
npm ci
npm ci --ignore-scripts
echo "=== Version Information ==="
echo "Node version:"
@@ -101,7 +101,7 @@ jobs:
$config | ConvertTo-Json -Depth 10 | Set-Content tauri.conf.json
- name: build and publish
uses: tauri-apps/tauri-action@v0
uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0
env:
# NB(bt): This is needed by wreq. Hopefully it doesn't kill Tauri
RUSTFLAGS: "-C target-feature=+crt-static"
+3 -3
View File
@@ -5,14 +5,14 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="SwaggerUI" />
<title>Storyteller API</title>
<link rel="stylesheet" href="//unpkg.com/swagger-ui-dist@5.32.0/swagger-ui.css" />
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.32.0/swagger-ui.css" integrity="sha384-3nuX7df3EaAoiqLBeyS1Ola0Gpg9ryJKVtarubwfnA1cOH8AWHUdbPSIvEqPZ9VH" crossorigin="anonymous" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="//unpkg.com/swagger-ui-dist@5.32.0/swagger-ui-bundle.js" crossorigin></script>
<script src="//unpkg.com/swagger-ui-dist@5.32.0/swagger-ui-standalone-preset.js" crossorigin></script>
<script src="https://unpkg.com/swagger-ui-dist@5.32.0/swagger-ui-bundle.js" integrity="sha384-7xcoc6ZKDFF7Ek627QTC3Bg/K+5Y36NJ8MWAE43D2m6+3Sh9XO3tdsfHhrS8gNIQ" crossorigin="anonymous"></script>
<script src="https://unpkg.com/swagger-ui-dist@5.32.0/swagger-ui-standalone-preset.js" integrity="sha384-FjFI+0PRyd5aAEoduVmUYk65iDC5+onNzam4WJtbAKKBim/kWvGUMk/2+9qRaYZb" crossorigin="anonymous"></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
+1 -1
View File
@@ -17,7 +17,7 @@ set -euxo pipefail
echo 'TEMPORARY HACK: Build internal dependencies of artcraft since nx is not finding them...'
# A 'clean' will remove nx
npm install
npm install --ignore-scripts
# TODO: Temp commented out
nx build "@storyteller/api"
+3 -3
View File
@@ -37,11 +37,11 @@ rpmbuild --define "_topdir $work/rpmbuild" -bb rpmbuild/SPECS/artcraft.spec
find rpmbuild/RPMS -name '*.rpm' -exec cp {} target/x86_64-unknown-linux-gnu/release/bundle/rpm/ \;
printf 'appimage fixture\n' > target/x86_64-unknown-linux-gnu/release/bundle/appimage/ArtCraft.AppImage
"$script" x86_64 x86_64-unknown-linux-gnu
for format in deb rpm AppImage AppImage.zsync tar.gz; do test -s "dist/release/artcraft-0.42.0-linux-x86_64.$format"; done
for format in deb rpm AppImage AppImage.zsync tar.gz; do [[ -s "dist/release/artcraft-0.42.0-linux-x86_64.$format" ]]; done
mkdir unpacked
tar -xzf dist/release/artcraft-0.42.0-linux-x86_64.tar.gz -C unpacked
test -x unpacked/artcraft-0.42.0-linux-x86_64/bin/artcraft
test -f unpacked/artcraft-0.42.0-linux-x86_64/share/applications/ai.artcraft.app.desktop
[[ -x unpacked/artcraft-0.42.0-linux-x86_64/bin/artcraft ]]
[[ -f unpacked/artcraft-0.42.0-linux-x86_64/share/applications/ai.artcraft.app.desktop ]]
rm target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm
if "$script" x86_64 x86_64-unknown-linux-gnu; then
echo 'Packaging accepted a missing RPM' >&2
+1 -1
View File
@@ -31,7 +31,7 @@ if [[ "${desktops[0]}" != "$work/$base/share/applications/ai.artcraft.app.deskto
fi
install -Dm644 "$script_dir/ai.artcraft.app.metainfo.xml" "$work/$base/share/metainfo/ai.artcraft.app.metainfo.xml"
sed -i 's/^Name=.*/Name=ArtCraft Studio/' "$work/$base/share/applications/ai.artcraft.app.desktop"
test -x "$work/$base/bin/artcraft"
[[ -x "$work/$base/bin/artcraft" ]]
case "$arch" in
x86_64) machine='Advanced Micro Devices X86-64' ;;
aarch64) machine='AArch64' ;;
+1 -1
View File
@@ -15,7 +15,7 @@ config_path="${rust_crate_path}/tauri.conf.json"
pushd "${frontend_path}" || exit
npm install --verbose
npm install --ignore-scripts --verbose
popd || exit
+1 -1
View File
@@ -38,7 +38,7 @@ fi
cd "${frontend_path}"
if [[ ! -f node_modules/vite/package.json ]]; then
# Do not use the legacy install helper: its failure recovery deletes caches.
npm install
npm install --ignore-scripts
fi
exec node "${frontend_path}/scripts/unix-dev.mjs"
@@ -9,7 +9,7 @@ echo ""
pushd "${frontend_path}" || exit
npm install --verbose
npm install --ignore-scripts --verbose
export VITE_ENVIRONMENT_TYPE="production"
@@ -20,7 +20,7 @@ fi
pushd "${frontend_path}" || exit
npm install --verbose
npm install --ignore-scripts --verbose
export VITE_ENVIRONMENT_TYPE="production"
+8 -8
View File
@@ -16,7 +16,7 @@ FRONTEND_MINIMUM_NODE_MAJOR=20
frontend_preflight() {
local frontend_path="$1"
if [ ! -d "${frontend_path}" ]; then
if [[ ! -d "${frontend_path}" ]]; then
echo "ERROR: frontend directory not found at: ${frontend_path}"
echo "Run this script from the repository root."
exit 1
@@ -40,7 +40,7 @@ frontend_preflight() {
# --- 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
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
@@ -50,13 +50,13 @@ frontend_preflight() {
# 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
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"
echo " cd ${frontend_path} && rm -rf node_modules pnpm-lock.yaml pnpm-workspace.yaml && npm install --ignore-scripts"
exit 1
fi
}
@@ -66,7 +66,7 @@ frontend_preflight() {
# 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
if npm install --ignore-scripts; then
return 0
fi
@@ -77,7 +77,7 @@ frontend_npm_install() {
rm -rf node_modules .nx
if ! npm install; then
if ! npm install --ignore-scripts; then
echo ""
echo "ERROR: npm install failed again. See the npm output above and the"
echo "troubleshooting section in frontend/README.md."
+23
View File
@@ -6,3 +6,26 @@ sonar.organization=storytold
# as filmcraft and lightcraft excluding tools/docs/examples.
sonar.coverage.exclusions=**/*.ts,**/*.tsx,**/*.js,**/*.jsx
# Not analysed: code that isn't ArtCraft's or isn't run by the app or CI.
# - crates/vendor/: third-party crates kept in the tree.
# - The Python beside the Grok and Sora clients: the upstream reference implementations the Rust ports
# cite ("Based on Grok-Api/core/xctid.py"); nothing runs them.
# - frontend/scripts/unix-dev.mjs and frontend/tools/performance/: developer tools run by hand
# (script/artcraft/unix_dev.sh, `npm run perf:desktop`); they start git, cargo and a browser from
# the developer's own PATH and write where the developer says.
sonar.exclusions=crates/vendor/**,crates/api_clients/grok_consumer_client/src/credentials/_metadata/**,crates/api_clients/openai_sora_client/src/requests/auth_sentinel_2/metadata/python_impl/**,frontend/scripts/unix-dev.mjs,frontend/tools/performance/**
# S4347 (predictable seed): DeterministicRng is the fixed-seed generator for tests and dev seed
# tools; being reproducible is its purpose.
# S2187 (file without tests): the API tests build their cases with the shared helpers in
# test/app/Classes/ApiManager/utils/, which call `it` themselves.
# S2819 (message origin): a dedicated worker's `message` events come only from the page that
# started it; they carry no origin to check.
sonar.issue.ignore.multicriteria=deterministic_rng,api_test_helpers,worker_messages
sonar.issue.ignore.multicriteria.deterministic_rng.ruleKey=rust:S4347
sonar.issue.ignore.multicriteria.deterministic_rng.resourceKey=crates/schema/public/tokens/src/deterministic_rng.rs
sonar.issue.ignore.multicriteria.api_test_helpers.ruleKey=typescript:S2187
sonar.issue.ignore.multicriteria.api_test_helpers.resourceKey=frontend/apps/artcraft/test/app/Classes/ApiManager/**
sonar.issue.ignore.multicriteria.worker_messages.ruleKey=typescript:S2819
sonar.issue.ignore.multicriteria.worker_messages.resourceKey=**/*.worker.ts