Add File History Browser for versioned file snapshots #191
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ========================================== | |
| # UNIT TESTS WORKFLOW | |
| # ========================================== | |
| # This workflow runs the macOS app's unit test suite and lints the codebase. | |
| # It can be triggered in three ways: | |
| # 1. Automatically on pushes to main | |
| # 2. Automatically on pull requests to main | |
| # 3. Manually via workflow_dispatch with custom Xcode version | |
| # | |
| # The workflow uses xcodebuild for building and testing, with SwiftLint | |
| # for code quality enforcement. | |
| name: Unit Tests | |
| on: | |
| # ========================================== | |
| # AUTOMATIC TRIGGERS | |
| # ========================================== | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| # ========================================== | |
| # REUSABLE WORKFLOW TRIGGER | |
| # ========================================== | |
| # Allows this workflow to be called by other workflows | |
| workflow_call: | |
| inputs: | |
| xcode_version: | |
| description: 'Xcode Version' | |
| required: false | |
| default: 'Xcode_26.0.app' | |
| type: string | |
| # ========================================== | |
| # MANUAL TRIGGER | |
| # ========================================== | |
| # Allows manual execution with custom parameters | |
| workflow_dispatch: | |
| inputs: | |
| xcode_version: | |
| description: 'Xcode Version' | |
| required: false | |
| default: 'Xcode_26.0.app' | |
| type: choice | |
| options: | |
| - Xcode_26.0.app | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: macOS Tests | |
| runs-on: macos-latest | |
| timeout-minutes: 30 | |
| env: | |
| # Prevent macOS system gitconfig from loading osxkeychain | |
| # credential helper, which triggers a blocking Keychain dialog | |
| # on self-hosted runners. | |
| GIT_CONFIG_NOSYSTEM: true | |
| steps: | |
| # ========================================== | |
| # STEP 1: CHECKOUT CODE | |
| # ========================================== | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| # ========================================== | |
| # STEP 2: SETUP XCODE | |
| # ========================================== | |
| - name: Setup Xcode | |
| run: | | |
| XCODE_PATH="/Applications/${{ inputs.xcode_version || 'Xcode_26.0.app' }}" | |
| if [ -d "$XCODE_PATH" ]; then | |
| echo "DEVELOPER_DIR=$XCODE_PATH/Contents/Developer" >> $GITHUB_ENV | |
| echo "Using Xcode: $XCODE_PATH" | |
| else | |
| echo "::error::Xcode not found at $XCODE_PATH" | |
| ls /Applications/ | grep -i xcode || echo "No Xcode installations found" | |
| exit 1 | |
| fi | |
| # ========================================== | |
| # STEP 3: SETUP HOMEBREW | |
| # ========================================== | |
| - name: Setup Homebrew | |
| run: | | |
| if [ -f /opt/homebrew/bin/brew ]; then | |
| eval "$(/opt/homebrew/bin/brew shellenv)" | |
| elif [ -f /usr/local/bin/brew ]; then | |
| eval "$(/usr/local/bin/brew shellenv)" | |
| else | |
| echo "::error::Homebrew not found" | |
| exit 1 | |
| fi | |
| echo "$(brew --prefix)/bin" >> $GITHUB_PATH | |
| # ========================================== | |
| # STEP 4: INSTALL LINT & FORMAT TOOLS | |
| # ========================================== | |
| - name: Install SwiftLint & SwiftFormat | |
| run: brew install swiftlint swiftformat | |
| # ========================================== | |
| # STEP 5: COMPUTE METADATA | |
| # ========================================== | |
| - name: Compute short SHA and start time | |
| run: | | |
| echo "SHORT_SHA=${GITHUB_SHA::7}" >> "$GITHUB_ENV" | |
| echo "START_TIME=$(date +%s)" >> "$GITHUB_ENV" | |
| # ========================================== | |
| # STEP 6: BUILD FOR TESTING | |
| # ========================================== | |
| - name: Build | |
| run: | | |
| xcodebuild -scheme Poirot \ | |
| -destination 'platform=macOS' \ | |
| -skipMacroValidation \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| build-for-testing | |
| # ========================================== | |
| # STEP 7: RUN TESTS (uses build from step 6) | |
| # ========================================== | |
| - name: Test | |
| id: test | |
| run: | | |
| xcodebuild -scheme Poirot \ | |
| -destination 'platform=macOS' \ | |
| -skipMacroValidation \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| -resultBundlePath TestResults/Poirot.xcresult \ | |
| -skip-testing PoirotTests/ScreenshotTests_Analytics \ | |
| -skip-testing PoirotTests/ScreenshotTests_ConfigScreens \ | |
| -skip-testing PoirotTests/ScreenshotTests_DebugLog \ | |
| -skip-testing PoirotTests/ScreenshotTests_EditDiff \ | |
| -skip-testing PoirotTests/ScreenshotTests_Facets \ | |
| -skip-testing PoirotTests/ScreenshotTests_FullViews \ | |
| -skip-testing PoirotTests/ScreenshotTests_History \ | |
| -skip-testing PoirotTests/ScreenshotTests_Memory \ | |
| -skip-testing PoirotTests/ScreenshotTests_Plans \ | |
| -skip-testing PoirotTests/ScreenshotTests_SessionDetail \ | |
| -skip-testing PoirotTests/ScreenshotTests_Sidebar \ | |
| -skip-testing PoirotTests/ScreenshotTests_Standalone \ | |
| -skip-testing PoirotTests/ScreenshotTests_ThinkingBlocks \ | |
| -skip-testing PoirotTests/ScreenshotTests_Todos \ | |
| -skip-testing PoirotTests/ScreenshotTests_ToolBlocks \ | |
| -skip-testing PoirotTests/ScreenshotTests_Windows \ | |
| test-without-building | |
| # ========================================== | |
| # STEP 8: LINT | |
| # ========================================== | |
| - name: Lint | |
| if: always() && steps.test.outcome != 'cancelled' | |
| run: | | |
| swiftlint lint \ | |
| --config .swiftlint.yml \ | |
| Poirot/Sources \ | |
| --reporter github-actions-logging | |
| # ========================================== | |
| # STEP 9: UPLOAD TEST ARTIFACTS | |
| # ========================================== | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-${{ github.run_number }} | |
| path: | | |
| TestResults/*.xcresult | |
| retention-days: 21 | |
| # ========================================== | |
| # STEP 10: POST WORKFLOW SUMMARY | |
| # ========================================== | |
| - name: Post test summary | |
| if: always() | |
| run: | | |
| echo "## 🧪 Test Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ steps.test.outcome }}" = "success" ]; then | |
| echo "✅ **All tests passed successfully!**" >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ steps.test.outcome }}" = "failure" ]; then | |
| echo "❌ **Tests failed**" >> $GITHUB_STEP_SUMMARY | |
| if [ -d "TestResults" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Failure Details:" >> $GITHUB_STEP_SUMMARY | |
| XCRESULT=$(find TestResults -name "*.xcresult" -type d | head -n 1) | |
| if [ -n "$XCRESULT" ]; then | |
| xcrun xcresulttool get test-results summary --path "$XCRESULT" >> $GITHUB_STEP_SUMMARY 2>/dev/null || echo "Could not extract detailed test results" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| fi | |
| else | |
| echo "⚠️ **Tests did not complete**" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Configuration:" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Scheme:** Poirot" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Platform:** macOS" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Xcode:** ${{ inputs.xcode_version || 'Xcode_26.0.app' }}" >> $GITHUB_STEP_SUMMARY | |
| # ========================================== | |
| # STEP 11: CALCULATE DURATION | |
| # ========================================== | |
| - name: Calculate duration | |
| if: always() | |
| run: | | |
| END_TIME=$(date +%s) | |
| DURATION=$((END_TIME - START_TIME)) | |
| MINUTES=$((DURATION / 60)) | |
| SECONDS=$((DURATION % 60)) | |
| if [ $MINUTES -gt 0 ]; then | |
| echo "⏱️ Duration: ${MINUTES}m ${SECONDS}s" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "⏱️ Duration: ${SECONDS}s" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # ========================================== | |
| # STEP 12: FAIL JOB IF TESTS FAILED | |
| # ========================================== | |
| - name: Fail job if tests failed | |
| if: always() && steps.test.outcome == 'failure' | |
| run: | | |
| echo "❌ Tests failed - failing the job" | |
| exit 1 |