Merge pull request #5 from RealDyllon/codex/optional-tool-docs-tests #6
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
| name: Build and Release App | |
| on: | |
| pull_request: | |
| paths: | |
| - ColimaStack/** | |
| - ColimaStackTests/** | |
| - ColimaStackUITests/** | |
| - ColimaStack.xcodeproj/** | |
| - .github/workflows/app-release.yml | |
| push: | |
| branches: [main] | |
| tags: | |
| - 'v*' | |
| paths: | |
| - ColimaStack/** | |
| - ColimaStackTests/** | |
| - ColimaStackUITests/** | |
| - ColimaStack.xcodeproj/** | |
| - .github/workflows/app-release.yml | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: Release version, without the leading v. | |
| required: true | |
| default: '0.0.1' | |
| build_number: | |
| description: Optional CFBundleVersion override. Defaults to the workflow run number. | |
| required: false | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: app-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| APP_NAME: ColimaStack | |
| PROJECT_PATH: ColimaStack.xcodeproj | |
| SCHEME: ColimaStack | |
| CONFIGURATION: Release | |
| DERIVED_DATA_PATH: build/DerivedData | |
| EXPORT_PATH: build/export | |
| jobs: | |
| app-smoke-tests: | |
| name: App Smoke Tests (${{ matrix.runner }}) | |
| runs-on: ${{ matrix.runner }} | |
| needs: build | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| runner: [macos-14, macos-15, macos-26] | |
| steps: | |
| - name: Show runner platform | |
| run: | | |
| sw_vers | |
| - name: Download app artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ needs.build.outputs.artifact_name }} | |
| path: smoke-assets | |
| - name: Expand app artifact | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| archive_path="smoke-assets/${{ needs.build.outputs.artifact_name }}.zip" | |
| if [[ ! -f "$archive_path" ]]; then | |
| echo "Expected app archive not found at $archive_path" >&2 | |
| exit 1 | |
| fi | |
| mkdir -p smoke-app | |
| ditto -x -k "$archive_path" smoke-app | |
| - name: Launch app | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| app_path="smoke-app/${APP_NAME}.app" | |
| executable="$app_path/Contents/MacOS/${APP_NAME}" | |
| log_path="$RUNNER_TEMP/${APP_NAME}-${{ matrix.runner }}.log" | |
| if [[ ! -x "$executable" ]]; then | |
| echo "Expected app executable not found at $executable" >&2 | |
| exit 1 | |
| fi | |
| "$executable" --mock-data >"$log_path" 2>&1 & | |
| app_pid="$!" | |
| cleanup() { | |
| kill "$app_pid" >/dev/null 2>&1 || true | |
| wait "$app_pid" >/dev/null 2>&1 || true | |
| } | |
| trap cleanup EXIT | |
| for _ in {1..15}; do | |
| if ! kill -0 "$app_pid" >/dev/null 2>&1; then | |
| echo "App exited before the smoke test completed." >&2 | |
| cat "$log_path" >&2 || true | |
| exit 1 | |
| fi | |
| sleep 1 | |
| done | |
| echo "App stayed running during the smoke test." | |
| build: | |
| name: Build and Test | |
| runs-on: macos-15 | |
| outputs: | |
| version: ${{ steps.metadata.outputs.version }} | |
| build_number: ${{ steps.metadata.outputs.build_number }} | |
| artifact_name: ${{ steps.metadata.outputs.artifact_name }} | |
| release_tag: ${{ steps.metadata.outputs.release_tag }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Resolve version metadata | |
| id: metadata | |
| shell: bash | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| INPUT_BUILD_NUMBER: ${{ github.event.inputs.build_number }} | |
| INPUT_VERSION: ${{ github.event.inputs.version }} | |
| REF_NAME: ${{ github.ref_name }} | |
| REF_TYPE: ${{ github.ref_type }} | |
| RUN_NUMBER: ${{ github.run_number }} | |
| run: | | |
| set -euo pipefail | |
| project_version="$( | |
| xcodebuild -showBuildSettings \ | |
| -project "$PROJECT_PATH" \ | |
| -scheme "$SCHEME" \ | |
| -configuration "$CONFIGURATION" \ | |
| -destination 'generic/platform=macOS' \ | |
| -derivedDataPath "$DERIVED_DATA_PATH" \ | |
| | awk -F '= ' '/MARKETING_VERSION/ { print $2; exit }' | |
| )" | |
| if [[ -z "$project_version" ]]; then | |
| echo "Unable to resolve MARKETING_VERSION from Xcode build settings." >&2 | |
| exit 1 | |
| fi | |
| version="$project_version" | |
| if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then | |
| version="$INPUT_VERSION" | |
| elif [[ "$REF_TYPE" == "tag" ]]; then | |
| version="${REF_NAME#v}" | |
| fi | |
| build_number="$RUN_NUMBER" | |
| if [[ "$EVENT_NAME" == "workflow_dispatch" && -n "$INPUT_BUILD_NUMBER" ]]; then | |
| build_number="$INPUT_BUILD_NUMBER" | |
| fi | |
| if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Version must use x.y.z format, for example 0.0.1." >&2 | |
| exit 1 | |
| fi | |
| if [[ ! "$build_number" =~ ^[0-9]+$ ]]; then | |
| echo "Build number must be numeric." >&2 | |
| exit 1 | |
| fi | |
| release_tag="v${version}" | |
| artifact_name="${APP_NAME}-${version}-${build_number}" | |
| { | |
| echo "version=${version}" | |
| echo "build_number=${build_number}" | |
| echo "release_tag=${release_tag}" | |
| echo "artifact_name=${artifact_name}" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Run tests | |
| run: | | |
| xcodebuild test \ | |
| -project "$PROJECT_PATH" \ | |
| -scheme "$SCHEME" \ | |
| -configuration Debug \ | |
| -destination 'platform=macOS' \ | |
| -skip-testing:ColimaStackUITests \ | |
| -derivedDataPath "$DERIVED_DATA_PATH" \ | |
| -parallel-testing-enabled NO \ | |
| CODE_SIGNING_ALLOWED=NO | |
| - name: Build app | |
| run: | | |
| xcodebuild build \ | |
| -project "$PROJECT_PATH" \ | |
| -scheme "$SCHEME" \ | |
| -configuration "$CONFIGURATION" \ | |
| -destination 'generic/platform=macOS' \ | |
| -derivedDataPath "$DERIVED_DATA_PATH" \ | |
| MARKETING_VERSION="${{ steps.metadata.outputs.version }}" \ | |
| CURRENT_PROJECT_VERSION="${{ steps.metadata.outputs.build_number }}" \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| CODE_SIGNING_REQUIRED=NO \ | |
| CODE_SIGN_IDENTITY="" | |
| - name: Package app | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| app_path="$DERIVED_DATA_PATH/Build/Products/$CONFIGURATION/$APP_NAME.app" | |
| if [[ ! -d "$app_path" ]]; then | |
| echo "Expected app bundle not found at $app_path" >&2 | |
| exit 1 | |
| fi | |
| mkdir -p "$EXPORT_PATH" | |
| ditto -c -k --keepParent "$app_path" "$EXPORT_PATH/${{ steps.metadata.outputs.artifact_name }}.zip" | |
| shasum -a 256 "$EXPORT_PATH/${{ steps.metadata.outputs.artifact_name }}.zip" \ | |
| > "$EXPORT_PATH/${{ steps.metadata.outputs.artifact_name }}.zip.sha256" | |
| - name: Upload workflow artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ steps.metadata.outputs.artifact_name }} | |
| path: | | |
| ${{ env.EXPORT_PATH }}/${{ steps.metadata.outputs.artifact_name }}.zip | |
| ${{ env.EXPORT_PATH }}/${{ steps.metadata.outputs.artifact_name }}.zip.sha256 | |
| if-no-files-found: error | |
| release: | |
| name: Publish GitHub Release | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build | |
| - app-smoke-tests | |
| if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download app artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ needs.build.outputs.artifact_name }} | |
| path: release-assets | |
| - name: Create or update release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPOSITORY: ${{ github.repository }} | |
| TAG: ${{ needs.build.outputs.release_tag }} | |
| VERSION: ${{ needs.build.outputs.version }} | |
| BUILD_NUMBER: ${{ needs.build.outputs.build_number }} | |
| ARTIFACT_NAME: ${{ needs.build.outputs.artifact_name }} | |
| run: | | |
| set -euo pipefail | |
| notes="ColimaStack ${VERSION} (${BUILD_NUMBER})" | |
| if gh release view "$TAG" --repo "$REPOSITORY" >/dev/null 2>&1; then | |
| gh release upload "$TAG" release-assets/* --repo "$REPOSITORY" --clobber | |
| else | |
| gh release create "$TAG" release-assets/* \ | |
| --repo "$REPOSITORY" \ | |
| --title "ColimaStack ${VERSION}" \ | |
| --notes "$notes" | |
| fi |