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
72 changes: 72 additions & 0 deletions CI/tests/xcodebuild_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
xcodebuild_test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- name: Select Xcode version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable

- name: Install xcpretty
run: gem install xcpretty

- name: Run xcodebuild test
run: |
set -euo pipefail

# Guard: xcodebuild must be present
if ! command -v xcodebuild &>/dev/null; then
echo "::error::xcodebuild not found — this job must run on macos-latest"
exit 1
fi

# Guard: xcpretty must be present
if ! command -v xcpretty &>/dev/null; then
echo "::error::xcpretty not found — run: gem install xcpretty"
exit 1
fi

# Locate workspace or project at repo root (bash-3.2-safe — no mapfile)
workspace_count=0
project_count=0
found_path=""

for f in *.xcworkspace; do
[ -e "$f" ] || continue
workspace_count=$((workspace_count + 1))
found_path="$f"
done

for f in *.xcodeproj; do
[ -e "$f" ] || continue
project_count=$((project_count + 1))
found_path="$f"
done

total_count=$((workspace_count + project_count))

if [ "$total_count" -eq 0 ]; then
echo "::error::No Xcode workspace or project found"
exit 1
fi

if [ "$total_count" -gt 1 ]; then
echo "::error::Multiple Xcode workspaces/projects found (specify via SCHEME/PROJECT env)"
exit 1
fi

# Resolve scheme: honour env var, fall back to basename without extension
if [ -z "${SCHEME:-}" ]; then
basename_no_ext="${found_path%.*}"
SCHEME="$basename_no_ext"
fi

echo "ℹ️ Running xcodebuild test — scheme: $SCHEME"

xcodebuild test \
-scheme "$SCHEME" \
-destination 'platform=iOS Simulator,name=iPhone 15' \
| xcpretty \
&& echo "✅ xcodebuild tests passed" \
|| { echo "❌ xcodebuild tests failed"; exit 1; }
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ that projects compose into their own workflows.
| Laravel | tests | [CI/tests/laravel_tests.yml](https://github.com/prog-time/workflows/blob/main/CI/tests/laravel_tests.yml) |
| pytest | tests | [CI/tests/pytest.yml](https://github.com/prog-time/workflows/blob/main/CI/tests/pytest.yml) |
| RSpec | tests | [CI/tests/rspec.yml](https://github.com/prog-time/workflows/blob/main/CI/tests/rspec.yml) |
| xcodebuild test | tests | [CI/tests/xcodebuild_test.yml](https://github.com/prog-time/workflows/blob/main/CI/tests/xcodebuild_test.yml) (**macos-latest**) |

---

Expand Down Expand Up @@ -110,7 +111,8 @@ Workflows/
│ │ ├── jest.yml
│ │ ├── laravel_tests.yml
│ │ ├── pytest.yml
│ │ └── rspec.yml
│ │ ├── rspec.yml
│ │ └── xcodebuild_test.yml
│ └── shell/ # bash scripts (one per tool)
│ ├── linters/
│ │ ├── clippy.sh
Expand Down Expand Up @@ -138,7 +140,8 @@ Workflows/
│ │ └── trivy.sh
│ └── tests/
│ ├── cargo_test.sh
│ └── jest.sh
│ ├── jest.sh
│ └── xcodebuild_test.sh
├── CI/ # assembled output (ready to use)
│ ├── linters/
Expand Down Expand Up @@ -167,7 +170,8 @@ Workflows/
│ │ └── trivy.bats
│ ├── tests/
│ │ ├── cargo_test.bats
│ │ └── jest.bats
│ │ ├── jest.bats
│ │ └── xcodebuild_test.bats
│ └── helpers/
│ └── common.bash # shared test utilities (mocks, temp dirs)
Expand Down Expand Up @@ -287,6 +291,7 @@ shellcheck:
| `CI/tests/laravel_tests.yml` | Laravel test suite (PHP 8.2, SQLite, parallel) |
| `CI/tests/pytest.yml` | Python test suite (pytest) |
| `CI/tests/rspec.yml` | Ruby test suite (RSpec via Bundler) |
| `CI/tests/xcodebuild_test.yml` | Swift/iOS XCTest suite (`xcodebuild test` via xcpretty) — **macOS only** |

---

Expand Down
15 changes: 15 additions & 0 deletions scripts/CI/tests/xcodebuild_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
xcodebuild_test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- name: Select Xcode version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable

- name: Install xcpretty
run: gem install xcpretty

- name: Run xcodebuild test
run: bash scripts/shell/tests/xcodebuild_test.sh
58 changes: 58 additions & 0 deletions scripts/shell/tests/xcodebuild_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -euo pipefail

# Guard: xcodebuild must be present
if ! command -v xcodebuild &>/dev/null; then
echo "::error::xcodebuild not found — this job must run on macos-latest"
exit 1
fi

# Guard: xcpretty must be present
if ! command -v xcpretty &>/dev/null; then
echo "::error::xcpretty not found — run: gem install xcpretty"
exit 1
fi

# Locate workspace or project at repo root (bash-3.2-safe — no mapfile)
workspace_count=0
project_count=0
found_path=""

for f in *.xcworkspace; do
[ -e "$f" ] || continue
workspace_count=$((workspace_count + 1))
found_path="$f"
done

for f in *.xcodeproj; do
[ -e "$f" ] || continue
project_count=$((project_count + 1))
found_path="$f"
done

total_count=$((workspace_count + project_count))

if [ "$total_count" -eq 0 ]; then
echo "::error::No Xcode workspace or project found"
exit 1
fi

if [ "$total_count" -gt 1 ]; then
echo "::error::Multiple Xcode workspaces/projects found (specify via SCHEME/PROJECT env)"
exit 1
fi

# Resolve scheme: honour env var, fall back to basename without extension
if [ -z "${SCHEME:-}" ]; then
basename_no_ext="${found_path%.*}"
SCHEME="$basename_no_ext"
fi

echo "ℹ️ Running xcodebuild test — scheme: $SCHEME"

xcodebuild test \
-scheme "$SCHEME" \
-destination 'platform=iOS Simulator,name=iPhone 15' \
| xcpretty \
&& echo "✅ xcodebuild tests passed" \
|| { echo "❌ xcodebuild tests failed"; exit 1; }
41 changes: 41 additions & 0 deletions tests/tests/xcodebuild_test.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env bats

load "../helpers/common"

SCRIPT="$BATS_TEST_DIRNAME/../../scripts/shell/tests/xcodebuild_test.sh"

setup() {
setup_test_dir
mkdir -p "$TEST_DIR/bin"
export PATH="$TEST_DIR/bin:$PATH"

# Stub xcodebuild and xcpretty so the guards pass in structural tests
cat > "$TEST_DIR/bin/xcodebuild" <<'EOF'
#!/usr/bin/env bash
exit 0
EOF
chmod +x "$TEST_DIR/bin/xcodebuild"

cat > "$TEST_DIR/bin/xcpretty" <<'EOF'
#!/usr/bin/env bash
cat
EOF
chmod +x "$TEST_DIR/bin/xcpretty"
}

teardown() {
teardown_test_dir
}

@test "no workspace or project: exits 1 with no-project error" {
run bash "$SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" == *"::error::No Xcode workspace or project found"* ]]
}

@test "two workspaces present: exits 1 with disambiguation error" {
mkdir -p "App.xcworkspace" "Other.xcworkspace"
run bash "$SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" == *"::error::Multiple Xcode workspaces/projects found"* ]]
}
Loading