Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

native: block dirty/conflicted OTA builds

+81 -4
+17 -1
fedac/native/scripts/upload-release.sh
··· 59 59 60 60 BASE_URL="https://${DO_SPACES_BUCKET}.${DO_SPACES_REGION}.digitaloceanspaces.com" 61 61 62 - # Build version string from git (append -dirty if uncommitted changes) 62 + # Build version string from git. Dirty/conflicted uploads are blocked by default. 63 63 GIT_HASH=$(git -C "$SCRIPT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown") 64 + CONFLICT_FILES=$(git -C "$SCRIPT_DIR" diff --name-only --diff-filter=U 2>/dev/null || true) 65 + if [ -n "$CONFLICT_FILES" ]; then 66 + echo "Error: refusing upload with unresolved merge conflicts:" >&2 67 + echo "$CONFLICT_FILES" >&2 68 + exit 1 69 + fi 70 + DIRTY_TRACKED=0 64 71 if ! git -C "$SCRIPT_DIR" diff --quiet HEAD 2>/dev/null; then 72 + DIRTY_TRACKED=1 73 + fi 74 + if [ "$DIRTY_TRACKED" -eq 1 ] && [ "${ALLOW_DIRTY_UPLOAD:-0}" != "1" ]; then 75 + echo "Error: refusing dirty upload. Commit/stash/reset native changes first." >&2 76 + git -C "$SCRIPT_DIR" status --porcelain --untracked-files=no -- fedac/native 2>/dev/null >&2 || true 77 + echo "Override only for emergencies: ALLOW_DIRTY_UPLOAD=1 ./scripts/upload-release.sh ..." >&2 78 + exit 1 79 + fi 80 + if [ "$DIRTY_TRACKED" -eq 1 ]; then 65 81 GIT_HASH="${GIT_HASH}-dirty" 66 82 fi 67 83 BUILD_TS=$(date -u '+%Y-%m-%dT%H:%M')
+60
oven/native-builder.mjs
··· 287 287 288 288 const repoDir = path.resolve(NATIVE_DIR, "../.."); 289 289 290 + // Preflight: hard-sync build repo and refuse conflicted/dirty native trees. 291 + addLogLine(job, "stdout", "Preflight: syncing native git checkout..."); 292 + await runPhase(job, "preflight-sync", "bash", ["-lc", [ 293 + "set -euo pipefail", 294 + "git fetch origin main --quiet || true", 295 + "git checkout -f main --quiet || true", 296 + "if git rev-parse --verify origin/main >/dev/null 2>&1; then", 297 + " git reset --hard origin/main --quiet", 298 + "fi", 299 + "git clean -fdq -- fedac/native", 300 + ].join("\n")], repoDir); 301 + 302 + const syncedRef = await runSync("git", ["rev-parse", "HEAD"], repoDir); 303 + if (syncedRef) job.ref = syncedRef; 304 + 305 + const trackedDirty = await runSync( 306 + "git", 307 + ["status", "--porcelain", "--untracked-files=no", "--", "fedac/native"], 308 + repoDir, 309 + ); 310 + if (trackedDirty) { 311 + throw new Error( 312 + `Refusing native build: fedac/native tree is dirty after sync:\n${trackedDirty}`, 313 + ); 314 + } 315 + 316 + const unresolved = await runSync( 317 + "git", 318 + ["diff", "--name-only", "--diff-filter=U", "--", "fedac/native"], 319 + repoDir, 320 + ); 321 + if (unresolved) { 322 + throw new Error( 323 + `Refusing native build: unresolved merge conflict(s): ${unresolved}`, 324 + ); 325 + } 326 + 327 + const conflictMarkers = await runSync( 328 + "bash", 329 + [ 330 + "-lc", 331 + "grep -nE '^(<<<<<<<|=======|>>>>>>>)|Updated upstream|Stashed changes' fedac/native/initramfs/init 2>/dev/null || true", 332 + ], 333 + repoDir, 334 + ); 335 + if (conflictMarkers) { 336 + throw new Error( 337 + `Refusing native build: conflict markers detected in initramfs/init:\n${conflictMarkers}`, 338 + ); 339 + } 340 + 341 + // Parse-check init script explicitly so syntax issues fail before kernel compile/upload. 342 + await runPhase( 343 + job, 344 + "preflight-init", 345 + "bash", 346 + ["-lc", "set -euo pipefail\nsh -n fedac/native/initramfs/init"], 347 + repoDir, 348 + ); 349 + 290 350 // Resolve ref from git HEAD if manual trigger didn't provide one 291 351 if (!job.ref || job.ref === "unknown") { 292 352 const headRef = await runSync("git", ["rev-parse", "HEAD"], repoDir);
+4 -3
oven/native-git-poller.mjs
··· 95 95 return; 96 96 } 97 97 98 - // Pull the changes so build-and-flash.sh works on up-to-date code 99 - await git(["checkout", BRANCH, "--quiet"]); 100 - await git(["merge", `origin/${BRANCH}`, "--ff-only", "--quiet"]); 98 + // Hard-sync to origin so stale local edits/conflicts cannot leak into OTA builds. 99 + await git(["checkout", "-f", BRANCH, "--quiet"]); 100 + await git(["reset", "--hard", `origin/${BRANCH}`, "--quiet"]); 101 + await git(["clean", "-fdq"]); 101 102 102 103 logFn( 103 104 "info",