Skip to content
Merged
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
8 changes: 4 additions & 4 deletions .github/actions/run-built-app-e2e/action.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Run built application E2E
description: >-
Runs the isolated built-application suite, restores and verifies the
production frontend, records optional startup measurements, and retains
Runs the isolated built-application suite, builds and verifies the
production frontend independently, records optional startup measurements, and retains
platform-scoped reliability evidence.

inputs:
Expand Down Expand Up @@ -39,10 +39,10 @@ runs:
bun run e2e
fi

- name: Recheck production build after E2E
- name: Build and check production frontend independently
shell: bash
if: ${{ always() }}
run: bun run e2e:isolation
run: bun run frontend:build && bun run e2e:isolation

- name: Measure large-fixture startup
id: startup_benchmark
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/setup-project/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ runs:

- name: Install Rust
if: inputs.rust-targets == ''
uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable branch (2026-06-30)
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable branch (2026-07-16)
with:
toolchain: ${{ steps.rust-toolchain.outputs.channel }}
components: clippy,rustfmt

- name: Install Rust with additional targets
if: inputs.rust-targets != ''
uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable branch (2026-06-30)
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable branch (2026-07-16)
with:
toolchain: ${{ steps.rust-toolchain.outputs.channel }}
targets: ${{ inputs.rust-targets }}
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/validate-build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ runs:

- name: Install cargo-audit
shell: bash
run: cargo install cargo-audit --locked
run: node scripts/install-cargo-audit.mjs

- name: Audit Rust dependencies
shell: bash
Expand Down
17 changes: 16 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ concurrency:
env:
CARGO_TERM_COLOR: always
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
RPM_SMOKE_IMAGE: fedora:43@sha256:781b7642e8bf256e9cf75d2aa58d86f5cc695fd2df113517614e181a5eee9138
TAURI_TARGET: x86_64-unknown-linux-gnu

jobs:
Expand Down Expand Up @@ -195,7 +196,9 @@ jobs:
rpm2cpio \
libarchive-tools \
desktop-file-utils \
appstream
appstream \
xauth \
xvfb

- name: Build frontend
run: bun run frontend:build
Expand Down Expand Up @@ -228,6 +231,18 @@ jobs:
fi
exit "${validator_status}"

- name: Install deb and launch deb and AppImage on Ubuntu
run: node scripts/smoke-release-artifacts.mjs --linux-deb-appimage dist/rust/artifacts

- name: Install and launch RPM with dependency resolution on Fedora
run: |
docker run --rm \
--volume "${PWD}:/workspace:ro" \
--volume "$(command -v bun):/usr/local/bin/bun:ro" \
--workdir /workspace \
"${RPM_SMOKE_IMAGE}" \
bun scripts/smoke-release-artifacts.mjs --linux-rpm dist/rust/artifacts

- name: Validate APT repository generation
run: node scripts/check-apt-repository.mjs

Expand Down
89 changes: 85 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ concurrency:
env:
CARGO_TERM_COLOR: always
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
RPM_SMOKE_IMAGE: fedora:43@sha256:781b7642e8bf256e9cf75d2aa58d86f5cc695fd2df113517614e181a5eee9138

jobs:
release-context:
Expand Down Expand Up @@ -257,20 +258,33 @@ jobs:

certificate_path="${RUNNER_TEMP}/developer-id.p12"
keychain_path="${RUNNER_TEMP}/qa-scribe-signing.keychain-db"
previous_keychains_path="${RUNNER_TEMP}/qa-scribe-previous-keychains.txt"
previous_keychains_staging_path="${previous_keychains_path}.next"
keychain_password="$(uuidgen)"
api_key_path="${RUNNER_TEMP}/AuthKey_${APPLE_API_KEY_ID}.p8"
MACOS_DEVELOPER_ID="${MACOS_DEVELOPER_ID_INPUT}"
MACOS_TEAM_ID="${MACOS_TEAM_ID_INPUT}"
echo "APPLE_API_KEY_PATH=${api_key_path}" >> "$GITHUB_ENV"

printf '%s' "$CSC_LINK" | base64 --decode > "$certificate_path"
printf '%s' "$APPLE_API_KEY_BASE64" | base64 --decode > "$api_key_path"

security list-keychains -d user | awk -F'"' 'NF >= 2 { print $2 }' > "$previous_keychains_staging_path"
mv "$previous_keychains_staging_path" "$previous_keychains_path"
previous_keychains=()
while IFS= read -r previous_keychain; do
[ -n "$previous_keychain" ] && previous_keychains+=("$previous_keychain")
done < "$previous_keychains_path"

security create-keychain -p "$keychain_password" "$keychain_path"
security set-keychain-settings -lut 21600 "$keychain_path"
security unlock-keychain -p "$keychain_password" "$keychain_path"
security import "$certificate_path" -k "$keychain_path" -P "$CSC_KEY_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
security list-keychains -d user -s "$keychain_path"
security default-keychain -d user -s "$keychain_path"
if [ ${#previous_keychains[@]} -gt 0 ]; then
security list-keychains -d user -s "$keychain_path" "${previous_keychains[@]}"
else
security list-keychains -d user -s "$keychain_path"
fi
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$keychain_password" "$keychain_path"

if [ -z "${MACOS_DEVELOPER_ID}" ]; then
Expand All @@ -296,7 +310,6 @@ jobs:
if [ -n "${MACOS_TEAM_ID}" ]; then
echo "MACOS_TEAM_ID=${MACOS_TEAM_ID}" >> "$GITHUB_ENV"
fi
echo "APPLE_API_KEY_PATH=${api_key_path}" >> "$GITHUB_ENV"

- name: Sign and notarize macOS app bundle
env:
Expand Down Expand Up @@ -345,6 +358,57 @@ jobs:
- name: Validate macOS artifacts
run: node scripts/check-rust-artifacts.mjs --platform macos --require-dmg

- name: Clean up Apple signing environment
if: always()
run: |
set -euo pipefail

keychain_path="${RUNNER_TEMP}/qa-scribe-signing.keychain-db"
certificate_path="${RUNNER_TEMP}/developer-id.p12"
previous_keychains_path="${RUNNER_TEMP}/qa-scribe-previous-keychains.txt"
previous_keychains_staging_path="${previous_keychains_path}.next"
api_key_path="${APPLE_API_KEY_PATH:-}"
if [ -n "${api_key_path}" ] && [[ "${api_key_path}" != "${RUNNER_TEMP}"/AuthKey_*.p8 ]]; then
echo "Refusing to remove unexpected Apple API key path: ${api_key_path}" >&2
exit 1
fi

cleanup_failed=0
if [ -f "${previous_keychains_path}" ]; then
previous_keychains=()
while IFS= read -r previous_keychain; do
[ -n "$previous_keychain" ] && previous_keychains+=("$previous_keychain")
done < "$previous_keychains_path"
if [ ${#previous_keychains[@]} -gt 0 ]; then
security list-keychains -d user -s "${previous_keychains[@]}" || cleanup_failed=1
else
security list-keychains -d user -s || cleanup_failed=1
fi
fi

security delete-keychain "${keychain_path}" >/dev/null 2>&1 || true
rm -f "${keychain_path}" "${certificate_path}" "${previous_keychains_path}" "${previous_keychains_staging_path}"
if [ -n "${api_key_path}" ]; then
rm -f "${api_key_path}"
fi

for sensitive_path in "${keychain_path}" "${certificate_path}" "${api_key_path}"; do
[ -n "${sensitive_path}" ] || continue
if [ -e "${sensitive_path}" ]; then
echo "Could not remove temporary Apple signing material: ${sensitive_path}" >&2
exit 1
fi
done

echo 'APPLE_API_KEY_PATH=' >> "${GITHUB_ENV}"
if [ "${cleanup_failed}" -ne 0 ]; then
echo 'Could not restore the original user keychain search list.' >&2
exit 1
fi

- name: Mount, copy, and launch final macOS DMG
run: node scripts/smoke-release-artifacts.mjs --macos-dmg dist/rust/artifacts

- name: Stage macOS release assets
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down Expand Up @@ -389,7 +453,9 @@ jobs:
libarchive-tools \
desktop-file-utils \
appstream \
gnupg
gnupg \
xauth \
xvfb

- name: Build frontend
run: bun run frontend:build
Expand Down Expand Up @@ -426,6 +492,18 @@ jobs:
fi
exit "${validator_status}"

- name: Install deb and launch deb and AppImage on Ubuntu
run: node scripts/smoke-release-artifacts.mjs --linux-deb-appimage dist/rust/artifacts

- name: Install and launch RPM with dependency resolution on Fedora
run: |
docker run --rm \
--volume "${PWD}:/workspace:ro" \
--volume "$(command -v bun):/usr/local/bin/bun:ro" \
--workdir /workspace \
"${RPM_SMOKE_IMAGE}" \
bun scripts/smoke-release-artifacts.mjs --linux-rpm dist/rust/artifacts

- name: Build signed APT repository and checksums
env:
DEB_SIGNING_PRIVATE_KEY: ${{ secrets.DEB_SIGNING_PRIVATE_KEY }}
Expand Down Expand Up @@ -511,6 +589,9 @@ jobs:
"${RUNNER_TEMP}/linux-signing-public-key.asc" \
"${RUNNER_TEMP}/linux-signing-passphrase"

- name: Install and verify final APT setup package
run: node scripts/smoke-release-artifacts.mjs --apt-setup dist/rust/artifacts/qa-scribe-repository-setup_1.0_all.deb --expected-keyring dist/rust/artifacts/qa-scribe-archive-keyring.pgp

- name: Stage APT repository installer
env:
LINUX_GPG_FINGERPRINT: ${{ secrets.DEB_SIGNING_KEY_FINGERPRINT }}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ __pycache__/
*.pyc
qa-scribe.sqlite
qa-scribe.sqlite-*
.qa-scribe-version-transaction.json*
**/.*.qa-scribe-bump-*
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## v0.7.21 - 2026-07-21

- Preserve authored Session work across recovered Summary completion, overlapping saves, blank-title validation, discard, navigation, active-Session reselection, and application close.
- Clean up abandoned image imports, add safe attachment deletion, and recover managed attachment previews with deduplicated reads and bounded automatic retries.
- Harden local AI execution with broadcast-first cancellation, private neutral working directories, bounded diagnostics, stricter structured-response parsing, and exact Evidence image identity.
- Make validation and releases more deterministic with isolated E2E builds, pinned audit tooling, recoverable version transactions, and dependency-resolving final-package installation and launch smokes.
- Split oversized persistence, controller, action, and regression-test modules along cohesive boundaries, backed by a traceable codebase audit and expanded race coverage.

## v0.7.20 - 2026-07-15

- Preserve the latest Testware and Finding edits across overlapping saves, Session changes, and hydration, while rejecting malformed navigation routes and empty AI-generated content before it can replace authored work.
Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ members = [
resolver = "3"

[workspace.package]
version = "0.7.20"
version = "0.7.21"
edition = "2024"
license = "MIT"
authors = ["qa-scribe contributors"]
Expand Down
1 change: 1 addition & 0 deletions build/linux/io.github.ddv1982.qa-scribe.metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<category>ProjectManagement</category>
</categories>
<releases>
<release version="0.7.21" date="2026-07-21" />
<release version="0.7.20" date="2026-07-15" />
<release version="0.7.19" date="2026-07-14" />
<release version="0.7.18" date="2026-07-14" />
Expand Down
Loading
Loading