Skip to content
Open
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
177 changes: 177 additions & 0 deletions .github/workflows/beta-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
name: Beta Release

on:
push:
branches:
- develop
workflow_dispatch:
inputs:
dry_run:
description: "Build/package without publishing"
required: true
default: true
type: boolean

concurrency:
group: beta-release
cancel-in-progress: true

permissions:
contents: write

jobs:
lint:
name: Lint
runs-on: macos-15

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

- name: Install SwiftLint
run: |
if ! command -v swiftlint >/dev/null 2>&1; then
brew install swiftlint
fi

- name: Run SwiftLint
run: swiftlint lint Spaceman --config .swiftlint.yml --reporter github-actions-logging --strict --no-cache

test:
name: Test
runs-on: macos-15
needs: lint

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

- name: Install xcbeautify
run: |
if ! command -v xcbeautify >/dev/null 2>&1; then
brew install xcbeautify
fi

- name: Build and Test
run: |
set -o pipefail
xcodebuild \
-project Spaceman.xcodeproj \
-scheme Spaceman \
-configuration Debug \
-destination 'platform=macOS' \
CODE_SIGNING_ALLOWED=NO \
CODE_SIGNING_REQUIRED=NO \
test \
| xcbeautify --renderer github-actions || exit $?

beta-release:
name: Archive and Publish Beta
runs-on: macos-15
needs: test
env:
APP_NAME: Spaceman
PROJECT_PATH: Spaceman.xcodeproj
SCHEME_NAME: Spaceman
ARTIFACTS_DIR: beta-artifacts
ALLOW_UNSIGNED_ARCHIVE: "1"
SPARKLE_PRIVATE_ED_KEY: ${{ secrets.SPARKLE_PRIVATE_ED_KEY }}

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set beta release context
run: |
dry_run="${{ github.event.inputs.dry_run || 'false' }}"

# Derive version from project file
marketing_version="$(
grep -Eo 'MARKETING_VERSION = [^;]+' "$PROJECT_PATH/project.pbxproj" \
| awk '{print $3}' \
| sort -u \
| head -n 1
)"

short_sha="$(git rev-parse --short HEAD)"
beta_version="${marketing_version}-beta.${short_sha}"
release_tag="beta-latest"

echo "RELEASE_TAG=$release_tag" >> "$GITHUB_ENV"
echo "RELEASE_VERSION=$beta_version" >> "$GITHUB_ENV"
echo "RELEASE_TITLE=Spaceman $beta_version (Beta)" >> "$GITHUB_ENV"
echo "SPARKLE_PUBLIC_BASE_URL=https://github.com/${GITHUB_REPOSITORY}/releases/download/$release_tag/" >> "$GITHUB_ENV"
echo "DRY_RUN=$dry_run" >> "$GITHUB_ENV"

- name: Validate required configuration
run: |
[[ -n "$SPARKLE_PRIVATE_ED_KEY" ]] || { echo "::error::Missing secret SPARKLE_PRIVATE_ED_KEY"; exit 1; }

- name: Prepare release directory
run: mkdir -p "$ARTIFACTS_DIR"

- name: Archive app and create DMG
run: ./scripts/release/build_dmg.sh "$RELEASE_VERSION" "$ARTIFACTS_DIR"

- name: Build Sparkle tool
run: echo "GENERATE_APPCAST_BIN=$(./scripts/release/build_sparkle_tool.sh generate_appcast)" >> "$GITHUB_ENV"

- name: Download existing beta appcast
if: env.DRY_RUN != 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
if gh release download beta-latest --repo "$GITHUB_REPOSITORY" --pattern appcast.xml --dir "$ARTIFACTS_DIR" 2>/dev/null; then
echo "Downloaded existing beta appcast.xml"
else
echo "No existing beta appcast.xml found, creating a new feed."
fi

- name: Generate appcast
env:
SPARKLE_MAX_VERSIONS: "1"
run: ./scripts/release/generate_appcast.sh "$ARTIFACTS_DIR"

- name: Publish beta GitHub release
if: env.DRY_RUN != 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
dmg_file="$ARTIFACTS_DIR/Spaceman-$RELEASE_VERSION.dmg"
appcast_file="$ARTIFACTS_DIR/appcast.xml"

[[ -f "$dmg_file" ]] || { echo "::error::DMG not found at $dmg_file"; exit 1; }
[[ -f "$appcast_file" ]] || { echo "::error::appcast.xml not found"; exit 1; }

notes="Beta build from develop branch.

Commit: ${{ github.sha }}
Version: $RELEASE_VERSION"

if gh release view beta-latest --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
# Delete old assets, update the release
gh release delete beta-latest --repo "$GITHUB_REPOSITORY" --yes
fi

gh release create beta-latest \
--repo "$GITHUB_REPOSITORY" \
--title "$RELEASE_TITLE" \
--notes "$notes" \
--prerelease \
--target develop

gh release upload beta-latest \
"$dmg_file" \
"$appcast_file" \
--repo "$GITHUB_REPOSITORY" \
--clobber

echo "https://github.com/${GITHUB_REPOSITORY}/releases/tag/beta-latest"

- name: Upload workflow artifacts
uses: actions/upload-artifact@v4
with:
name: sparkle-beta-${{ env.RELEASE_VERSION }}
path: beta-artifacts/
20 changes: 0 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,6 @@ jobs:
- name: Run SwiftLint
run: swiftlint lint --config .swiftlint.yml --reporter github-actions-logging --strict --no-cache

format:
# Advisory until .swift-format rules are calibrated against the
# existing codebase. Kept visible in CI so drift is surfaced, but
# not a gate on merges yet.
name: swift-format (advisory)
runs-on: macos-15
continue-on-error: true

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

- name: Run swift-format lint
run: |
swift-format lint \
--configuration .swift-format \
--recursive \
--strict \
Spaceman SpacemanTests

build-test:
name: Build and Test
runs-on: macos-15
Expand Down
29 changes: 1 addition & 28 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,7 @@ jobs:
PROJECT_PATH: Spaceman.xcodeproj
SCHEME_NAME: Spaceman
ARTIFACTS_DIR: release-artifacts
RELEASE_CODE_SIGN_IDENTITY: Developer ID Application
RELEASE_CODE_SIGN_STYLE: Manual
RELEASE_DEVELOPMENT_TEAM: ${{ secrets.APPLE_DEVELOPER_TEAM_ID }}
ALLOW_UNSIGNED_ARCHIVE: "1"
SPARKLE_PRIVATE_ED_KEY: ${{ secrets.SPARKLE_PRIVATE_ED_KEY }}
INPUT_RELEASE_TAG: ${{ github.event.inputs.release_tag }}
INPUT_TARGET_REF: ${{ github.event.inputs.target_ref }}
Expand Down Expand Up @@ -152,35 +150,10 @@ jobs:
- name: Validate required configuration
run: |
[[ -n "$SPARKLE_PRIVATE_ED_KEY" ]] || { echo "::error::Missing secret SPARKLE_PRIVATE_ED_KEY"; exit 1; }
[[ -n "$RELEASE_DEVELOPMENT_TEAM" ]] || { echo "::error::Missing secret APPLE_DEVELOPER_TEAM_ID"; exit 1; }

- name: Validate release version
run: ./scripts/release/validate_release_version.sh "$RELEASE_TAG"

- name: Import Developer ID certificate
env:
APPLE_DEVELOPER_ID_CERT_P12_BASE64: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12_BASE64 }}
APPLE_DEVELOPER_ID_CERT_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_CERT_PASSWORD }}
APPLE_KEYCHAIN_PASSWORD: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
run: |
[[ -n "$APPLE_DEVELOPER_ID_CERT_P12_BASE64" ]] || { echo "::error::Missing secret APPLE_DEVELOPER_ID_CERT_P12_BASE64"; exit 1; }
[[ -n "$APPLE_DEVELOPER_ID_CERT_PASSWORD" ]] || { echo "::error::Missing secret APPLE_DEVELOPER_ID_CERT_PASSWORD"; exit 1; }
[[ -n "$APPLE_KEYCHAIN_PASSWORD" ]] || { echo "::error::Missing secret APPLE_KEYCHAIN_PASSWORD"; exit 1; }

KEYCHAIN_PATH="$RUNNER_TEMP/build-signing.keychain-db"
CERT_PATH="$RUNNER_TEMP/developer-id.p12"

echo "$APPLE_DEVELOPER_ID_CERT_P12_BASE64" | base64 --decode > "$CERT_PATH"

security create-keychain -p "$APPLE_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$APPLE_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security import "$CERT_PATH" -k "$KEYCHAIN_PATH" -P "$APPLE_DEVELOPER_ID_CERT_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple: -s -k "$APPLE_KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychains -d user -s "$KEYCHAIN_PATH"

echo "RELEASE_OTHER_CODE_SIGN_FLAGS=--keychain $KEYCHAIN_PATH" >> "$GITHUB_ENV"

- name: Prepare release directory
run: mkdir -p "$ARTIFACTS_DIR"

Expand Down
64 changes: 0 additions & 64 deletions .swift-format

This file was deleted.

10 changes: 4 additions & 6 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ analyzer_rules:
- capture_variable

opt_in_rules:
- anyobject_protocol
- array_init
- closure_end_indentation
- closure_spacing
- collection_alignment
- contains_over_filter_count
- contains_over_filter_is_empty
Expand Down Expand Up @@ -48,8 +46,6 @@ opt_in_rules:
- legacy_multiple
- legacy_objc_type
- literal_expression_end_indentation
- lower_acl_than_parent
- multiline_arguments
- operator_usage_whitespace
- overridden_super_call
- pattern_matching_keywords
Expand All @@ -71,11 +67,13 @@ opt_in_rules:
- unneeded_parentheses_in_closure_argument
- unowned_variable_capture
- vertical_parameter_alignment_on_call
- vertical_whitespace_closing_braces
- vertical_whitespace_opening_braces
- weak_delegate
- yoda_condition

large_tuple:
warning: 3
error: 4

line_length:
warning: 120
error: 200
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The meaning of the icons from left to right are:

The style and the name of a space can be changed in preferences (shown above). A space is named by selecting the space from the dropdown, typing a name up to 3 characters and clicking the 'Update name' button or pressing enter.

If the icon fails to update, you can choose to force a refresh of the icon using a custom keyboard shortcut or allow Spaceman to refresh them automatically every 5 seconds by enabling 'Refresh spaces in background'. See [#2](https://github.com/Jaysce/Spaceman/issues/2).
If the icon fails to update, you can choose to force a refresh of the icon using a custom keyboard shortcut or allow Spaceman to refresh them automatically every 5 seconds by enabling 'Refresh spaces in background'. See [#2](https://github.com/yeapea/Spaceman/issues/2).

## Attributions
- This project is based on [WhichSpace](https://github.com/gechr/WhichSpace)
Expand Down
Loading
Loading