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
5 changes: 2 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

# Swift is written with tabs here, which is what Xcode does by default and what SwiftLint checks.
# Match the Swift source style.
[*.swift]
indent_style = tab

# YAML forbids tabs outright, and adding a site entry — the contribution this project asks for most —
# is editing a YAML file. An editor told to indent with tabs turns that into a syntax error.
# YAML requires spaces.
[*.{yml,yaml,json}]
indent_style = space
indent_size = 2
Expand Down
29 changes: 20 additions & 9 deletions CONTRIBUTING.md → .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,25 @@ the first one is being discussed.

## Building it

You need Xcode 26 or later — CI fails outright below that, so a change built
on an older one is a red run rather than a review. Nothing else is required to
build: dependencies come in through Swift Package Manager and Xcode resolves
them on first open.
Install Xcode 26 or later. The build uses its resource and App Intents tools;
Command Line Tools alone are insufficient. You do not need to open the IDE.

```
```sh
git clone https://github.com/PathGao/Nifro.git
open Nifro/Nifro.xcodeproj
cd Nifro
./build.sh
```

Then build and run the `Nifro` scheme.
The app is written to `.xcode-build/Build/Products/Release/Nifro.app`. Development
builds use `com.pathgao.nifro.dev` and `nifro-dev:` so they have separate preferences
and sandbox storage from the installed release. They are ad-hoc signed; macOS may
ask again for permissions after a rebuild. Nothing is installed or launched.

`./build.sh ci` builds unsigned Debug code. `./build.sh release` uses the production
identity and requires `APPLE_SIGNING_IDENTITY` and `APPLE_TEAM_ID`. For notarization
and publishing, see [the release guide](../docs/RELEASE.md).
Use `./build.sh --help` for options. Xcode remains available for debugging with
the `Nifro` scheme.

- **Swift 6 language mode.** Concurrency errors are errors, not warnings. If
you hit one, the fix is almost always to move the work onto the actor that
Expand All @@ -60,7 +68,7 @@ Then build and run the `Nifro` scheme.
it. There is no back-compatibility to preserve.
- **SwiftLint** runs as a build phase, so a clean build means a clean lint.
Install it with `brew install swiftlint`; without it the build phase warns
and continues. The rules live in `.swiftlint.yml`, which uses `only_rules`
and continues. The rules live in `Tools/Config/SwiftLint.yml`, which uses `only_rules`
— the enabled set is exactly what is listed there. If a rule is genuinely
wrong for your code, say so in the pull request rather than adding a
`swiftlint:disable` in silence.
Expand All @@ -82,7 +90,7 @@ falls on the description of what you ran. See below.
## Where things live

```
Nifro/
Sources/Nifro/
├── App/ entry point, state, events, menus, Shortcuts, URL commands
├── Wallpaper/ the window, the web view, loading, content rules, scroll restoration
├── Visibility/ the menu bar colour band, and dimming when another app is in front
Expand Down Expand Up @@ -160,3 +168,6 @@ What follows from that:

Contributions are made under the repository's MIT licence, the same one Nifro
inherited. There is no CLA and no bot to sign.

The share extension lives in `Sources/ShareExtension/`. The Xcode project and build
configuration live under `Tools/`; tests remain in `Tests/`.
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# only so `swift test` can compile the pure-logic files. The app's four real
# dependencies (Defaults, KeyboardShortcuts, LaunchAtLogin-Modern,
# swift-syntax) are resolved by the Xcode project, in
# Nifro.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved,
# Tools/Nifro.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved,
# which Dependabot does not parse. Adding a `swift` entry here would open no
# pull requests and quietly imply coverage that does not exist. Those four are
# bumped by hand in Xcode.
Expand Down
22 changes: 8 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,13 @@ jobs:
uses: actions/cache@v6
with:
path: .xcode-build/SourcePackages
key: spm-${{ hashFiles('Nifro.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}
key: spm-${{ hashFiles('Tools/Nifro.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}
restore-keys: spm-

# Signing needs a certificate we deliberately do not put in CI. Release signing lives in release.yml.
- name: Build
run: |
xcodebuild build \
-project Nifro.xcodeproj \
-scheme Nifro \
-configuration Debug \
-destination 'platform=macOS' \
-derivedDataPath .xcode-build \
CODE_SIGNING_ALLOWED=NO \
./build.sh ci \
| xcbeautify --renderer github-actions
env:
NSUnbufferedIO: YES
Expand Down Expand Up @@ -102,7 +96,7 @@ jobs:

# The Xcode build runs SwiftLint too, but only after compiling. Running it separately puts style feedback on a PR in under a minute.
- name: Lint
run: swiftlint lint --strict --reporter github-actions-logging
run: swiftlint lint --config Tools/Config/SwiftLint.yml --strict --reporter github-actions-logging

unused:
name: Unused code
Expand Down Expand Up @@ -132,11 +126,11 @@ jobs:
env:
PERIPHERY_VERSION: "2.21.2"

# Config, retentions and the reasoning behind each one live in .periphery.yml.
# Config, retentions and the reasoning behind each one live in Tools/Config/Periphery.yml.
# This inherited a 5,700-line utilities file copied wholesale from another
# project; without a gate it grows back.
- name: Scan
run: periphery scan --strict
run: periphery scan --config Tools/Config/Periphery.yml --strict

sites:
name: Site registry
Expand Down Expand Up @@ -209,7 +203,7 @@ jobs:
python3 - <<'CHECK'
import json, pathlib, sys

catalogue = json.loads(pathlib.Path("Nifro/Localizable.xcstrings").read_text())
catalogue = json.loads(pathlib.Path("Sources/Nifro/Localizable.xcstrings").read_text())
missing = [
key
for key, entry in catalogue["strings"].items()
Expand All @@ -228,8 +222,8 @@ jobs:
- name: Check the generated catalogue is current
run: |
python3 Tools/generate-site-catalog.py
if ! git diff --quiet -- sites/index.json Nifro/Sites/SiteCatalog.generated.swift; then
if ! git diff --quiet -- sites/index.json Sources/Nifro/Sites/SiteCatalog.generated.swift; then
echo "::error::sites/ changed without regenerating. Run Tools/generate-site-catalog.py and commit the result."
git diff --stat -- sites/index.json Nifro/Sites/SiteCatalog.generated.swift
git diff --stat -- sites/index.json Sources/Nifro/Sites/SiteCatalog.generated.swift
exit 1
fi
15 changes: 4 additions & 11 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ on:
default: false

env:
XCODE_PROJECT: Nifro.xcodeproj
XCODE_SCHEME: Nifro
BUILT_APP_NAME: Nifro.app
APP_NAME: Nifro
BUNDLE_ID: com.pathgao.nifro
Expand Down Expand Up @@ -61,15 +59,15 @@ jobs:
major="$(xcodebuild -version | sed -n '1s/Xcode \([0-9]*\).*/\1/p')"
[ "$major" -ge 26 ] || { echo "::error::Xcode $major is too old; this project needs 26 or newer"; exit 1; }

# `Config.xcconfig` is the only place a version is written. The tag is derived from it rather
# `Tools/Config/App.xcconfig` is the only place a version is written. The tag is derived from it rather
# than typed alongside it, so the two cannot disagree -- which they used to be able to, and the
# workflow's answer was to fail after being dispatched.
- name: Work out the version, and refuse to reuse one
id: version
run: |
set -euo pipefail

version="$(sed -n 's/^MARKETING_VERSION *= *//p' Config.xcconfig | tr -d ' \r')"
version="$(sed -n 's/^MARKETING_VERSION *= *//p' Tools/Config/App.xcconfig | tr -d ' \r')"
tag="v$version"

case "$version" in
Expand All @@ -82,7 +80,7 @@ jobs:
# A `v*` tag cannot be moved or deleted, so a second release of one is not something to
# recover from afterwards. Refused here, before anything is built.
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
echo "::error::$tag already exists. Bump MARKETING_VERSION in Config.xcconfig first."
echo "::error::$tag already exists. Bump MARKETING_VERSION in Tools/Config/App.xcconfig first."
exit 1
fi

Expand Down Expand Up @@ -186,12 +184,7 @@ jobs:
rm -rf .xcode-build/Build/Products

# ONLY_ACTIVE_ARCH=NO with a single ARCHS: a thin binary holding only this architecture.
xcodebuild clean build \
-project "$XCODE_PROJECT" \
-scheme "$XCODE_SCHEME" \
-configuration Release \
-destination "generic/platform=macOS" \
-derivedDataPath .xcode-build \
APPLE_SIGNING_IDENTITY="$identity" APPLE_TEAM_ID="$TEAM_ID" ./build.sh release \
ARCHS="$arch" \
ONLY_ACTIVE_ARCH=NO \
"${signing_args[@]}" \
Expand Down
111 changes: 0 additions & 111 deletions .periphery.yml

This file was deleted.

8 changes: 0 additions & 8 deletions Config.xcconfig

This file was deleted.

12 changes: 0 additions & 12 deletions Nifro/Nifro.icon/Assets/Rectangle 2 2.svg

This file was deleted.

56 changes: 0 additions & 56 deletions Nifro/Nifro.icon/icon.json

This file was deleted.

Loading
Loading