diff --git a/.github/workflows/VerifyChanges.yaml b/.github/workflows/VerifyChanges.yaml new file mode 100644 index 0000000..6764a03 --- /dev/null +++ b/.github/workflows/VerifyChanges.yaml @@ -0,0 +1,128 @@ +name: Verify Changes + +on: + merge_group: + pull_request: + branches: "**" + push: + branches: ["main"] + +jobs: + lint: + name: Lint + runs-on: macos-15 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Select Xcode 16.4 + run: | + sudo xcode-select -s /Applications/Xcode_16.4.0.app + - name: Lint + run: | + Scripts/lint + build-and-test: + name: Build and Test (${{ matrix.platform }}) + needs: lint + runs-on: macos-15 + strategy: + fail-fast: false + matrix: + include: + - platform: iOS + xcode_destination: "platform=iOS Simulator,name=iPhone 16 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)" + env: + DEV_BUILDS: DevBuilds/Sources + XCCOV_PRETTY_VERSION: 1.2.0 + XCODE_SCHEME: DevConfiguration + XCODE_DESTINATION: ${{ matrix.xcode_destination }} + XCODE_TEST_PLAN: DevConfiguration + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Checkout DevBuilds + uses: actions/checkout@v4 + with: + repository: DevKitOrganization/DevBuilds + path: DevBuilds + - name: Download xccovPretty + if: github.event_name != 'push' + run: | + gh release download ${{ env.XCCOV_PRETTY_VERSION }} \ + --repo DevKitOrganization/xccovPretty \ + --pattern "xccovPretty-macos.tar.gz" \ + -O - | tar -xz + chmod +x xccovPretty + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: irgaly/xcode-cache@v1 + with: + key: xcode-cache-deriveddata-${{ github.workflow }}-${{ matrix.platform }}-${{ github.sha }} + restore-keys: | + xcode-cache-deriveddata-${{ github.workflow }}-${{ matrix.platform }}- + xcode-cache-deriveddata- + deriveddata-directory: .build/DerivedData + sourcepackages-directory: .build/DerivedData/SourcePackages + swiftpm-package-resolved-file: | + **/*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved + Package.resolved + verbose: true + - name: Select Xcode 16.4 + run: | + sudo xcode-select -s /Applications/Xcode_16.4.0.app + - name: Build for Testing + run: | + "$DEV_BUILDS"/build_and_test.sh --action build-for-testing + - name: Test + if: github.event_name != 'push' + run: | + "$DEV_BUILDS"/build_and_test.sh --action test + - name: Log Code Coverage + if: github.event_name != 'push' + run: | + xcrun xccov view --report .build/DevConfiguration_test.xcresult --json \ + | ./xccovPretty --github-comment \ + > .build/xccovPretty-${{ matrix.platform }}.output + - name: Upload Logs + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: Logs-${{ matrix.platform }} + path: .build/*.log + include-hidden-files: true + - name: Upload XCResults + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: XCResults-${{ matrix.platform }} + path: .build/*.xcresult + include-hidden-files: true + - name: Upload xccovPretty output + if: github.event_name != 'push' + uses: actions/upload-artifact@v4 + with: + name: xccovPrettyOutput-${{ matrix.platform }} + path: .build/xccovPretty-${{ matrix.platform }}.output + include-hidden-files: true + post-pr-comments: + name: Post PR Comments + needs: build-and-test + permissions: + pull-requests: write + runs-on: ubuntu-latest + if: ${{ github.event_name == 'pull_request' }} + steps: + - name: Download xccovPretty output + uses: actions/download-artifact@v4 + with: + name: xccovPrettyOutput-iOS + - name: Post Code Coverage Comment + uses: thollander/actions-comment-pull-request@v3 + with: + file-path: xccovPretty-iOS.output + comment-tag: codeCoverage-iOS diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..6cd31d6 --- /dev/null +++ b/.swift-format @@ -0,0 +1,75 @@ +{ + "fileScopedDeclarationPrivacy": { + "accessLevel": "private" + }, + "indentConditionalCompilationBlocks": false, + "indentSwitchCaseLabels": false, + "indentation": { + "spaces": 4 + }, + "lineBreakAroundMultilineExpressionChainComponents": false, + "lineBreakBeforeControlFlowKeywords": false, + "lineBreakBeforeEachArgument": false, + "lineBreakBeforeEachGenericRequirement": false, + "lineBreakBetweenDeclarationAttributes": false, + "lineLength": 120, + "maximumBlankLines": 2, + "multiElementCollectionTrailingCommas": true, + "noAssignmentInExpressions": { + "allowedFunctions": [] + }, + "prioritizeKeepingFunctionOutputTogether": true, + "reflowMultilineStringLiterals": { + "never": {} + }, + "respectsExistingLineBreaks": true, + "rules": { + "AllPublicDeclarationsHaveDocumentation": false, + "AlwaysUseLiteralForEmptyCollectionInit": true, + "AlwaysUseLowerCamelCase": true, + "AmbiguousTrailingClosureOverload": true, + "AvoidRetroactiveConformances": false, + "BeginDocumentationCommentWithOneLineSummary": true, + "DoNotUseSemicolons": true, + "DontRepeatTypeInStaticProperties": true, + "FileScopedDeclarationPrivacy": true, + "FullyIndirectEnum": true, + "GroupNumericLiterals": true, + "IdentifiersMustBeASCII": true, + "NeverForceUnwrap": false, + "NeverUseForceTry": false, + "NeverUseImplicitlyUnwrappedOptionals": false, + "NoAccessLevelOnExtensionDeclaration": true, + "NoAssignmentInExpressions": true, + "NoBlockComments": true, + "NoCasesWithOnlyFallthrough": true, + "NoEmptyLinesOpeningClosingBraces": false, + "NoEmptyTrailingClosureParentheses": true, + "NoLabelsInCasePatterns": true, + "NoLeadingUnderscores": false, + "NoParensAroundConditions": true, + "NoPlaygroundLiterals": true, + "NoVoidReturnOnFunctionSignature": true, + "OmitExplicitReturns": false, + "OneCasePerLine": true, + "OneVariableDeclarationPerLine": true, + "OnlyOneTrailingClosureArgument": true, + "OrderedImports": true, + "ReplaceForEachWithForLoop": true, + "ReturnVoidInsteadOfEmptyTuple": true, + "TypeNamesShouldBeCapitalized": true, + "UseEarlyExits": true, + "UseExplicitNilCheckInConditions": true, + "UseLetInEveryBoundCaseVariable": true, + "UseShorthandTypeNames": true, + "UseSingleLinePropertyGetter": true, + "UseSynthesizedInitializer": true, + "UseTripleSlashForDocumentationComments": true, + "UseWhereClausesInForLoops": true, + "ValidateDocumentationComments": false + }, + "spacesAroundRangeFormationOperators": true, + "spacesBeforeEndOfLineComments": 4, + "tabWidth": 4, + "version": 1 +} diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/DevConfiguration.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/DevConfiguration.xcscheme new file mode 100644 index 0000000..3848aeb --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/DevConfiguration.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Build Support/Test Plans/DevConfiguration.xctestplan b/Build Support/Test Plans/DevConfiguration.xctestplan new file mode 100644 index 0000000..1e6fa8d --- /dev/null +++ b/Build Support/Test Plans/DevConfiguration.xctestplan @@ -0,0 +1,34 @@ +{ + "configurations" : [ + { + "id" : "D4211755-E8F7-47FF-8191-92A8AE4F1284", + "name" : "Test Scheme Action", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:", + "identifier" : "DevConfiguration", + "name" : "DevConfiguration" + } + ] + }, + "defaultTestExecutionTimeAllowance" : 60, + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "DevConfigurationTests", + "name" : "DevConfigurationTests" + } + } + ], + "version" : 1 +} diff --git a/Scripts/install-git-hooks b/Scripts/install-git-hooks new file mode 100755 index 0000000..670ea93 --- /dev/null +++ b/Scripts/install-git-hooks @@ -0,0 +1,50 @@ +#!/bin/bash + +# Get the directory where this script is located +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 + 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." + exit 1 +fi + +echo "Lint check passed." +EOF + + chmod +x "$pre_commit_hook" + echo "Pre-commit hook installed successfully!" +} + +# Install the pre-commit hook +install_pre_commit_hook + +echo "All git hooks installed successfully!" +echo "The pre-commit hook will run 'Scripts/lint' before each commit." diff --git a/Scripts/lint b/Scripts/lint new file mode 100755 index 0000000..8e11414 --- /dev/null +++ b/Scripts/lint @@ -0,0 +1,10 @@ +#!/bin/bash + +# Get the directory where this script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Go to the repository root (one level up from Scripts) +REPO_ROOT="$(dirname "$SCRIPT_DIR")" + +# Run swift format lint with full paths to preserve user's PWD +swift format lint --recursive --strict "$REPO_ROOT/Sources/" "$REPO_ROOT/Tests/" diff --git a/Tests/DevConfigurationTests/DevConfigurationTests.swift b/Tests/DevConfigurationTests/DevConfigurationTests.swift new file mode 100644 index 0000000..3923844 --- /dev/null +++ b/Tests/DevConfigurationTests/DevConfigurationTests.swift @@ -0,0 +1,19 @@ +// +// DevConfigurationTests.swift +// DevConfiguration +// +// Created by Duncan Lewis on 7/11/25. +// + +import DevTesting +import Foundation +import Testing +@testable import DevConfiguration + +struct DevConfigurationTests { + @Test + func testReverseDNSPrefix() { + let result = reverseDNSPrefixed("test") + #expect(result == "com.gauriar.devconfiguration.test") + } +}