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
7 changes: 7 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(Scripts/lint)"
]
}
}
58 changes: 23 additions & 35 deletions .github/workflows/VerifyChanges.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,22 @@ on:
push:
branches: ["main"]

env:
XCODE_VERSION: 26.0.1

jobs:
lint:
name: Lint
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Select Xcode ${{ env.XCODE_VERSION }}
run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app
- name: Lint
run: |
Scripts/lint

build-and-test:
name: Build and Test (${{ matrix.platform }})
needs: lint
runs-on: macos-26
strategy:
fail-fast: false
matrix:
include:
# - platform: iOS
# xcode_destination: "platform=iOS Simulator,name=iPhone 17 Pro"
- platform: iOS
xcode_destination: "platform=iOS Simulator,name=iPhone 17 Pro"
- platform: macOS
xcode_destination: "platform=macOS,arch=arm64"
# - platform: tvOS
# xcode_destination: "platform=tvOS Simulator,name=Apple TV 4K (3rd generation)"
# - platform: watchOS
# xcode_destination: "platform=watchOS Simulator,name=Apple Watch Series 10 (46mm)"
- platform: tvOS
xcode_destination: "platform=tvOS Simulator,name=Apple TV 4K (3rd generation)"
- platform: watchOS
xcode_destination: "platform=watchOS Simulator,name=Apple Watch Series 11 (46mm)"

env:
DEV_BUILDS: DevBuilds/Sources
Expand All @@ -47,39 +31,43 @@ jobs:
XCODE_DESTINATION: ${{ matrix.xcode_destination }}
XCODE_TEST_PLAN: DevTesting
XCODE_TEST_PRODUCTS_PATH: .build/DevTesting.xctestproducts
XCODE_VERSION: 26.3

steps:
- name: Select Xcode ${{ env.XCODE_VERSION }}
run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app
run: sudo xcode-select -s /Applications/Xcode_"$XCODE_VERSION".app

- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Checkout DevBuilds
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
repository: DevKitOrganization/DevBuilds
path: DevBuilds

- name: Restore XCTestProducts
if: github.event_name != 'push'
id: cache-xctestproducts-restore
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: ${{ env.XCODE_TEST_PRODUCTS_PATH }}
key: cache-xctestproducts-${{ github.workflow }}-${{ matrix.platform }}-${{ github.sha }}

- name: Lint
if: steps.cache-xctestproducts-restore.outputs.cache-hit != 'true'
run: Scripts/lint

- uses: irgaly/xcode-cache@v1
if: steps.cache-xctestproducts-restore.outputs.cache-hit != 'true'
with:
key: xcode-cache-deriveddata-${{ github.workflow }}-${{ matrix.platform }}-${{ github.sha }}
key: xcode-cache-deriveddata-${{ env.XCODE_VERSION }}-${{ github.workflow }}-${{ matrix.platform }}-${{ github.sha }}
restore-keys: |
xcode-cache-deriveddata-${{ github.workflow }}-${{ matrix.platform }}-
xcode-cache-deriveddata-
xcode-cache-deriveddata-${{ env.XCODE_VERSION }}-${{ github.workflow }}-${{ matrix.platform }}-
xcode-cache-deriveddata-${{ env.XCODE_VERSION }}
deriveddata-directory: .build/DerivedData
sourcepackages-directory: .build/DerivedData/SourcePackages
swiftpm-package-resolved-file: Package.resolved
verbose: true

- name: Build for Testing
id: build-for-testing
Expand All @@ -92,8 +80,8 @@ jobs:
run: ${{ env.DEV_BUILDS }}/build_and_test.sh --action test-without-building

- name: Save XCTestProducts
if: failure() && steps.cache-xctestproducts-restore.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
if: (cancelled() || failure()) && steps.cache-xctestproducts-restore.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: ${{ env.XCODE_TEST_PRODUCTS_PATH }}
key: ${{ steps.cache-xctestproducts-restore.outputs.cache-primary-key }}
Expand All @@ -116,7 +104,7 @@ jobs:

- name: Upload Logs and XCResults
if: success() || failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Logs_and_XCResults-${{ matrix.platform }}
path: |
Expand All @@ -126,7 +114,7 @@ jobs:

- name: Upload xccovPretty output
if: github.event_name != 'push'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: xccovPrettyOutput-${{ matrix.platform }}
path: .build/xccovPretty-${{ matrix.platform }}.output
Expand All @@ -142,7 +130,7 @@ jobs:

steps:
- name: Download xccovPretty output
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: xccovPrettyOutput-macOS

Expand Down
4 changes: 2 additions & 2 deletions .swift-format
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@
"ReplaceForEachWithForLoop": true,
"ReturnVoidInsteadOfEmptyTuple": true,
"TypeNamesShouldBeCapitalized": true,
"UseEarlyExits": true,
"UseEarlyExits": false,
"UseExplicitNilCheckInConditions": true,
"UseLetInEveryBoundCaseVariable": true,
"UseShorthandTypeNames": true,
"UseSingleLinePropertyGetter": true,
"UseSynthesizedInitializer": true,
"UseTripleSlashForDocumentationComments": true,
"UseWhereClausesInForLoops": true,
"UseWhereClausesInForLoops": false,
"ValidateDocumentationComments": false
},
"spacesAroundRangeFormationOperators": true,
Expand Down
36 changes: 25 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,11 @@ repository.
- **Swift format configuration**: Uses `.swift-format` file with 4-space indentation and 120
character line length

### Platform Testing

- **Test all platforms**: `Scripts/test-all-platforms` (runs tests on iOS, macOS, tvOS, and
watchOS simulators using xcodebuild)

### Git Hooks

- **Install git hooks**: `Scripts/install-git-hooks` (installs both pre-commit and pre-push
hooks)
- **Pre-commit hook**: Automatically runs `Scripts/lint` before each commit
- **Pre-push hook**: Automatically runs `Scripts/test-all-platforms` before each push
- **Install git hooks**: `Scripts/install-git-hooks` (installs pre-push hook; supports git
worktrees)
- **Pre-push hook**: Automatically runs `Scripts/lint` before each push

### Documentation

Expand Down Expand Up @@ -80,8 +74,28 @@ reproducibility.
- **Test Plans**: Uses `DevTesting.xctestplan` for organized test execution
- **Coverage Target**: Aims for 99%+ test coverage
- **Platform Testing**: Tests run on iOS, macOS, tvOS, and watchOS simulators
- **CI/CD**: GitHub Actions workflow runs builds on macOS only (iOS, tvOS, and watchOS builds
disabled due to stability/reliability issues)
- **CI/CD**: GitHub Actions workflow runs builds on iOS, macOS, tvOS, and watchOS

### Code Style Conventions

- Always use `where` clauses to declare constraints on generic parameters
- Prefer `Float64` over `Double` and `Float32` over `Float`
- Always attribute files to the current user, not Claude (e.g., "Created by <current user>
on mm/dd/yyyy")

#### Code Formatting and Spacing

- **2 blank lines between major sections** including:
- Between the last property declaration and first function declaration
- Between all function/computed property implementations at the same scope level
- Between top-level type declarations (class, struct, enum, protocol, extension)
- Before MARK comments that separate major sections
- **1 blank line** for minor separations:
- Between property declarations and nested type definitions
- Between all function definitions in protocols
- After headers in documentation
- After MARK comments that separate major sections
- **File endings**: All Swift files must end with exactly one blank line

### Documentation Standards

Expand Down
3 changes: 1 addition & 2 deletions Documentation/MarkdownStyleGuide.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Markdown Style Guide

This document defines the Markdown formatting standards for documentation in the Shopper iOS
codebase.
This document defines the Markdown formatting standards for documentation in this codebase.


## General Formatting
Expand Down
13 changes: 4 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,20 @@ interfaces are fully documented and tested. We aim for overall test coverage ove

To set up the development environment:

1. Run `Scripts/install-git-hooks` to install git hooks that automatically check code
formatting on commits and run comprehensive tests before pushing.
1. Run `Scripts/install-git-hooks` to install the pre-push hook that automatically checks
code formatting before pushing.
2. Use `Scripts/lint` to manually check code formatting at any time.
3. Use `Scripts/test-all-platforms` to run tests on all supported platforms locally.
3. Use `Scripts/format` to auto-fix code formatting issues.


## Continuous Integration

DevTesting uses GitHub Actions for continuous integration. The CI pipeline:

- **Linting**: Automatically checks code formatting on all pull requests using `swift format`
- **Testing**: Runs tests on macOS (iOS, tvOS, and watchOS testing are disabled in CI due to
reliability issues)
- **Testing**: Runs tests on iOS, macOS, tvOS, and watchOS
- **Coverage**: Generates code coverage reports using xccovPretty

For comprehensive cross-platform testing, developers should run `Scripts/test-all-platforms`
locally or rely on the pre-push git hook which automatically runs all platform tests before
pushing changes.


## Bugs and Feature Requests

Expand Down
1 change: 0 additions & 1 deletion Scripts/format
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ REPO_ROOT="$(dirname "$SCRIPT_DIR")"

# Run swift format with --in-place to fix formatting issues
swift format --in-place --recursive \
"$REPO_ROOT/Packages/" \
"$REPO_ROOT/Sources/" \
"$REPO_ROOT/Tests/"
63 changes: 18 additions & 45 deletions Scripts/install-git-hooks
Original file line number Diff line number Diff line change
Expand Up @@ -6,78 +6,51 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Go to the repository root (one level up from Scripts)
REPO_ROOT="$(dirname "$SCRIPT_DIR")"

# Check if we're in a git repository
if [ ! -d "$REPO_ROOT/.git" ]; then
# Check if we're in a git repository and get the git directory
# This works for both regular repos and worktrees
cd "$REPO_ROOT"
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "Error: Not in a git repository"
exit 1
fi

mkdir -p "$REPO_ROOT/.git/hooks"

# Function to install the pre-commit hook
install_pre_commit_hook() {
local pre_commit_hook="$REPO_ROOT/.git/hooks/pre-commit"

echo "Installing pre-commit hook..."

cat > "$pre_commit_hook" << 'EOF'
#!/bin/bash

# Get the directory where this hook is located
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Go to the repository root (two levels up from .git/hooks)
REPO_ROOT="$(dirname "$(dirname "$HOOK_DIR")")"

# Run the lint script
echo "Running lint check..."
if ! "$REPO_ROOT/Scripts/lint"; then
echo "Lint check failed. Please fix formatting issues before committing."
# Get the common git directory (shared across all worktrees)
GIT_COMMON_DIR="$(git rev-parse --git-common-dir)"
if [ ! -d "$GIT_COMMON_DIR" ]; then
echo "Error: Could not find git directory"
exit 1
fi

echo "Lint check passed."
EOF

chmod +x "$pre_commit_hook"
echo "Pre-commit hook installed successfully!"
}
mkdir -p "$GIT_COMMON_DIR/hooks"

# Function to install the pre-push hook
install_pre_push_hook() {
local pre_push_hook="$REPO_ROOT/.git/hooks/pre-push"
local pre_push_hook="$GIT_COMMON_DIR/hooks/pre-push"

echo "Installing pre-push hook..."

cat > "$pre_push_hook" << 'EOF'
#!/bin/bash

# Get the directory where this hook is located
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Go to the repository root (two levels up from .git/hooks)
REPO_ROOT="$(dirname "$(dirname "$HOOK_DIR")")"
# Resolve the repository root using git, which correctly handles worktrees
REPO_ROOT="$(git rev-parse --show-toplevel)"

# Run the test-all-platforms script
echo "Running tests on all platforms..."
if ! "$REPO_ROOT/Scripts/test-all-platforms"; then
echo "Platform tests failed. Please fix issues before pushing."
# Run the lint script
echo "Running lint check..."
if ! "$REPO_ROOT/Scripts/lint"; then
echo "Lint check failed. Please fix formatting issues before pushing."
exit 1
fi

echo "All platform tests passed."
echo "Lint check passed."
EOF

chmod +x "$pre_push_hook"
echo "Pre-push hook installed successfully!"
}

# Install the pre-commit hook
install_pre_commit_hook

# Install the pre-push hook
install_pre_push_hook

echo "All git hooks installed successfully!"
echo "The pre-commit hook will run 'Scripts/lint' before each commit."
echo "The pre-push hook will run 'Scripts/test-all-platforms' before each push."
echo "The pre-push hook will run 'Scripts/lint' before each push."
Loading
Loading