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
27 changes: 27 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
# Posts the "Validate (local)" status for each pushed branch commit that
# scripts/validate.sh has already validated (see README.md#validation). It never
# blocks the push: a commit that hasn't been validated just doesn't get the
# check, and main won't accept it until it does.
#
# Enable once per clone: git config core.hooksPath .githooks

repo_root=$(git rev-parse --show-toplevel)
state_dir="$(cd "$repo_root" && cd "$(git rev-parse --git-common-dir)" && pwd)/validate"
mkdir -p "$state_dir/logs"

while read -r _local_ref local_sha remote_ref _remote_sha; do
case "$remote_ref" in refs/heads/*) ;; *) continue ;; esac
case "$local_sha" in *[!0]*) ;; *) continue ;; esac # deleting the branch

if [ -f "$state_dir/results/$local_sha" ]; then
# The commit only reaches GitHub after this hook returns, so post from the
# background once it's there.
nohup "$repo_root/scripts/validate.sh" --post "$local_sha" \
</dev/null >>"$state_dir/logs/post.log" 2>&1 &
else
echo "validate: ${local_sha:0:9} (${remote_ref#refs/heads/}) hasn't been validated; run 'make validate' in Vault/ to get the green check." >&2
fi
done

exit 0
203 changes: 0 additions & 203 deletions .github/workflows/validate-all.yml

This file was deleted.

4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ This root-level file only covers things that apply across the whole repo (the Sw

Read [`MANIFESTO.md`](./MANIFESTO.md) before proposing or implementing any feature that touches killphrases, search passphrases, lock state, authentication, telemetry, backups, exports, or anything in the Danger Zone. The manifesto is normative — when a proposed change conflicts with it, the manifesto wins unless it is amended first via a dedicated `MANIFESTO:` PR.

## Validation

There is no hosted CI. Before a PR can merge into `main`, its latest commit needs the **Validate (local)** status check, which is posted by running `make validate` in `Vault/`. See [Validation](./README.md#validation) in the README and the rules in [`Vault/AGENTS.md`](./Vault/AGENTS.md).

## Layout

- [`Vault/`](./Vault) — Swift Package with all targets, tests, and tooling. Open `Vault.xcworkspace` to work on it.
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,20 @@ As soon as we are able, we will be dropping the xcodeproj project wrapper and go
- `Vault.xcworkspace` what you should open
- `/Vault` Swift Package that defines targets used by the app, build settings, tooling.
- `/VaultApp` minimal wrapper that packages this into an executable application.

### Validation

There is no hosted CI. Changes are validated on the developer's Mac, and the result is posted to the commit on GitHub as the **Validate (local)** status check. `main` requires that check, so a PR can't be merged until its latest commit has passed.

1. Once per clone, enable the pre-push hook: `git config core.hooksPath .githooks`
2. Commit your changes, then run `make validate` from `/Vault`.

`make validate` ([`scripts/validate.sh`](./scripts/validate.sh)) checks out the exact commit into a separate worktree, so uncommitted changes and your usual DerivedData can't affect the result. It then runs, with Xcode 27.0:

- `make lint`
- the Fastlane config check (skipped, and noted on the check, if the Ruby version in `.ruby-version` isn't installed)
- a build and full run of the `iOSAllTests` test plan on a throwaway iPhone 18 Pro Max / iOS 27.0 simulator, created for the run and deleted afterwards

If the commit is already on GitHub, the result is posted straight away. Otherwise it's stored, and the pre-push hook posts it when you push, so you can validate before or after pushing. Every new commit needs validating again. Logs are kept in `.git/validate/logs/`.

The check is self-attested: it records that the commit passed on the machine that posted it, rather than on independent CI.
9 changes: 9 additions & 0 deletions Vault/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,12 @@ Use the simulator configuration specified in `README.md` for all builds and test
## Committing

Before every commit, run `make format` and `make lint` from the `Vault/` directory to ensure code is properly formatted and passes linting.

## Validating a Pull Request

There is no hosted CI. `main` only accepts a PR whose latest commit has the **Validate (local)** status check, and only `make validate` posts it (see [Validation](../README.md#validation)).

- Commit first, then run `make validate` from the `Vault/` directory. It validates the committed `HEAD` in a clean worktree, so uncommitted changes aren't covered.
- Run it again after every new commit on a PR branch: each commit needs its own check.
- If it fails, fix the problem, commit, and validate the new commit. Never post, edit or fake the status by hand (for example with `gh api .../statuses`), and don't work around a failing test to get a green check.
- It takes several minutes. Tell the user whether it passed, and if it didn't, which step failed and where its log is.
6 changes: 6 additions & 0 deletions Vault/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ lint:
swift package plugin --allow-writing-to-package-directory swiftlint --strict --quiet ./Sources
swift package --allow-writing-to-package-directory format --lint --sources=./

# Validation: lint, build and test the current commit in a clean worktree, then
# post the green "Validate (local)" check to GitHub. See ../README.md#validation.
.PHONY: validate
validate:
../scripts/validate.sh

# Marketing screenshots: capture raw shots of the app on throwaway simulators,
# then put them in device frames with titles. See Screenshots/README.md.
.PHONY: screenshots
Expand Down
4 changes: 4 additions & 0 deletions Vault/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ You shouldn't need to manually change the locale or any other simulator setting
<td>Lint Sources</td>
<td><b>make lint</b></td>
</tr>
<tr>
<td>Validate the current commit and post the green check to GitHub (see <a href="../README.md#validation">Validation</a>)</td>
<td><b>make validate</b></td>
</tr>
<tr>
<td>Force clean existing build artifacts</td>
<td><b>make clean</b></td>
Expand Down
Loading