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
57 changes: 21 additions & 36 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
# Version updates. Alerts and security updates are repository settings and need nothing
# here; this file is only the scheduled "bump things that are behind" pull requests.
# Version updates. Alerts are a repository setting and need nothing here; this file is only
# the scheduled "bump things that are behind" pull requests.
#
# Two settings below are load-bearing rather than taste, and both are explained where they
# appear: `target-branch`, because the default would aim at the release branch, and the
# `groups` blocks, because an ungrouped cargo update is expensive in a way that is not
# obvious from the diff.
# Only the workflows are covered. npm and cargo were here once and were taken out on purpose,
# so do not add them back without reading why:
#
# - Version updates only move what package.json and Cargo.toml name directly. Every alert
# the repository actually had was in a transitive crate (openssl, rustls-webpki, tar...),
# which these pull requests never touch - the grouped cargo one fixed none of the 20 open
# alerts it sat next to.
# - Each major arrives as its own pull request that fails CI until someone does the
# migration, and each cargo one rewrites Cargo.lock, which busts the Rust cache and
# compiles all 799 crates cold on three operating systems.
# - Security updates would target the alerts, but they always aim at the default branch,
# `main`, where a merge is the release decision. `target-branch` does not apply to them,
# so they stay switched off in the repository settings.
#
# Instead, dependencies are refreshed by hand on `develop` before a release (`cargo update`,
# `npm update`, then check the open alerts). Alerts read the lockfiles on `main`, so they
# close when that release is promoted.
version: 2

updates:
# The workflows themselves. This is the cheapest of the three and arguably the most
# useful: it is what would have flagged actions-rs/toolchain being archived in 2023,
# which test.yml had to notice by hand.
# The workflows themselves. This is cheap and useful: it is what would have flagged
# actions-rs/toolchain being archived in 2023, which test.yml had to notice by hand.
- package-ecosystem: "github-actions"
directory: "/"
# Dependabot aims at the default branch unless told otherwise, and the default branch
Expand All @@ -28,30 +40,3 @@ updates:
# ones that need reading.
actions-minor-and-patch:
update-types: ["minor", "patch"]

- package-ecosystem: "npm"
directory: "/"
target-branch: "develop"
schedule:
interval: "monthly"
open-pull-requests-limit: 3
groups:
npm-minor-and-patch:
update-types: ["minor", "patch"]

# The Rust crate. Grouping matters most here, and the reason is the Rust cache: its key
# includes a hash of Cargo.lock, so *any* crate bump is a cache miss, and the pull request
# then compiles all 799 crates cold on three operating systems. One grouped pull request a
# month pays that once; a pull request per crate would pay it over and over.
#
# The `drag` dependency is a git dependency (crabnebula-dev/drag-rs) and Dependabot does
# not update cargo git sources, so that one stays manual.
- package-ecosystem: "cargo"
directory: "/src-tauri"
target-branch: "develop"
schedule:
interval: "monthly"
open-pull-requests-limit: 3
groups:
cargo-minor-and-patch:
update-types: ["minor", "patch"]
57 changes: 57 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,52 @@ concurrency:
cancel-in-progress: true

jobs:
# The rust leg is the whole length of this workflow: six to eight minutes against about one
# for each of the other two, and caching the cargo registry was measured to save nothing.
# Almost none of that time is this repository's code. The extractor spends it resolving the
# 799 crates in Cargo.lock and reading their signatures, and the queries spend it on one
# shared pass over the database that builds - which is why all 37 finish together, and why
# dropping queries would not help. So a pull request that touches no Rust skips it.
#
# Only pull requests. The weekly schedule and a manual dispatch always analyse everything,
# which is what keeps the Security tab's baseline for main complete. A skipped PR shows a
# warning in the Code scanning check that the rust configuration was not found; that is the
# expected cost of skipping, not a failure.
rust-changes:
name: Rust changed?
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
outputs:
analyze: ${{ steps.check.outputs.analyze }}
steps:
- name: Look for changes the rust analysis would see
id: check
env:
GH_TOKEN: ${{ github.token }}
EVENT: ${{ github.event_name }}
PR: ${{ github.event.pull_request.number }}
run: |
analyze=true
# Every doubt resolves to analysing. A failed lookup reads as "no files", which
# would otherwise mean "no Rust" and skip the one thing this workflow is slow for.
if [ "$EVENT" = pull_request ] \
&& files=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR/files" --paginate --jq '.[].filename'); then
count=$(printf '%s\n' "$files" | grep -c . || true)
# The files endpoint stops at 3000. Past that the list is incomplete.
if [ "$count" -gt 0 ] && [ "$count" -lt 3000 ] \
&& ! printf '%s\n' "$files" | grep -qE '^(src-tauri/|\.github/workflows/codeql\.yml$)'; then
analyze=false
fi
echo "$count files changed; rust analysis: $analyze"
fi
echo "analyze=$analyze" >> "$GITHUB_OUTPUT"

analyze:
name: Analyze (${{ matrix.language }})
needs: rust-changes
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
Expand Down Expand Up @@ -60,17 +104,30 @@ jobs:
- language: rust
build-mode: none

# Decided per step rather than per job, because a job-level `if` is evaluated before the
# matrix expands and cannot see `matrix.language`. The skipped rust leg still reports, as a
# green job with a note in its summary, rather than vanishing from the PR.
env:
SKIP: ${{ matrix.language == 'rust' && needs.rust-changes.outputs.analyze != 'true' }}

steps:
- name: Note the skip
if: env.SKIP == 'true'
run: echo "No Rust changed in this pull request, so the rust analysis was skipped. The weekly scheduled run still covers it." >> "$GITHUB_STEP_SUMMARY"

- name: Checkout code
if: env.SKIP != 'true'
uses: actions/checkout@v7

- name: Initialize CodeQL
if: env.SKIP != 'true'
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

- name: Analyze
if: env.SKIP != 'true'
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{ matrix.language }}"
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,34 @@ popover, not for the person who wrote the commit.

## [Unreleased]

## [1.8.8] - 2026-09-25

### Changed
- **Approving a new computer is a tick, not a retyped code.** You had to read the sixteen
characters off one screen and type them into the other before the approve button would
appear. Your eyes had already done the comparing; the typing only added a chance to
mistype it and be told the codes did not match when they did. The code is shown large
enough to read across a desk, and you confirm it matches with a checkbox
- **Long stashes fold up in the queue.** A plan an agent filed through the MCP server, or a
stash after AI enhancement, could run to several screens, and scrolling past one to reach
the next item was most of the work of using the queue. A stash that is clearly taller
than the cap now stops at a fixed height with a fade, and Show more opens it, Show less
folds it back. Short stashes look exactly as before

### Fixed
- **A computer waiting to be let in notices when it has been.** After approving it from the
other machine, the one that was waiting went on saying it was waiting - the only way to
find out it had worked was to close the settings and open them again, which reads as the
approval having failed. It now picks the key up on its own, within a few seconds

### Security
- **The libraries built into the app are brought up to date with their security fixes.** This
covers the framework that hosts the app's window, the updater's archive unpacking, and the
TLS and certificate checks behind every connection to the sync server. None of the fixed
problems could be reached through anything Stashpad does today; this closes them before a
future change could make one reachable. The Linux build keeps one older GTK component with
a minor warning against it, until the framework moves off it

## [1.8.7] - 2026-09-24

### Fixed
Expand Down
6 changes: 0 additions & 6 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ npm run test:ui

# Run tests with coverage report
npm run test:coverage

# Run only unit tests
npm run test:unit

# Run only integration tests
npm run test:integration
```

### Backend Tests
Expand Down
Loading
Loading