#!/bin/bash # ##===----------------------------------------------------------------------===## ## ## This source file is part of the OpenSwiftUI open source project ## ## Copyright (c) 2025 the OpenSwiftUI project authors ## Licensed under Apache License v2.0 ## ## See LICENSE.txt for license information ## ## SPDX-License-Identifier: Apache-2.0 ## ##===----------------------------------------------------------------------===## set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" DOCS_DIR="$REPO_ROOT/.docs" BUILD_DIR="$DOCS_DIR/build" DOCC_OUTPUT_DIR="$BUILD_DIR/docc-output" # Default configuration BUILD_DOCS=true MINIMUM_ACCESS_LEVEL="public" TARGET_NAME="OpenSwiftUI" HOSTING_BASE_PATH="/OpenSwiftUI" CLEAN_BUILD=false SOURCE_SERVICE="github" SOURCE_SERVICE_BASE_URL="https://github.com/OpenSwiftUIProject/OpenSwiftUI/blob/main" FORCE_PUSH=true # Force push to save git repo size (avoids accumulating large binary files) ECHO_WITHOUT_PUSH=false # Echo push command without actually pushing # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color usage() { cat << EOF Usage: $(basename "$0") [OPTIONS] Publish Swift documentation to GitHub Pages using DocC. This legacy script will build documentation (or use existing build) and deploy it to the gh-pages branch for GitHub Pages hosting. The canonical deployment path is now .github/workflows/documentation.yml. OPTIONS: --no-build Skip building documentation (use existing output) --minimum-access-level LEVEL Set minimum access level (public, internal, private) Default: public --target TARGET Target to document (default: OpenSwiftUI) --hosting-base-path PATH Base path for hosting (default: /OpenSwiftUI) --source-service SERVICE Source service (github, gitlab, bitbucket) --source-service-base-url URL Base URL for source service (e.g., https://github.com/user/repo/blob/main) --no-force Don't force push (preserves gh-pages history) Default: force push to save repo size --clean Clean build artifacts and force rebuild --echo-without-push Echo push command without actually pushing (for testing) -h, --help Show this help message EXAMPLES: # Build and publish to GitHub Pages (source links enabled by default) $(basename "$0") # Publish using existing documentation build $(basename "$0") --no-build # Build with internal symbols and publish $(basename "$0") --minimum-access-level internal # Document a specific target $(basename "$0") --target OpenSwiftUICore # Build and publish with custom source service (e.g., for a fork) $(basename "$0") \\ --source-service github \\ --source-service-base-url https://github.com/yourname/OpenSwiftUI/blob/custom-branch EOF exit 0 } log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } git_push() { if [[ "$ECHO_WITHOUT_PUSH" == true ]]; then echo "[echo without push]: git push $*" else git push "$@" fi } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in --no-build) BUILD_DOCS=false shift ;; --minimum-access-level) MINIMUM_ACCESS_LEVEL="$2" shift 2 ;; --target) TARGET_NAME="$2" shift 2 ;; --hosting-base-path) HOSTING_BASE_PATH="$2" shift 2 ;; --source-service) SOURCE_SERVICE="$2" shift 2 ;; --source-service-base-url) SOURCE_SERVICE_BASE_URL="$2" shift 2 ;; --no-force) FORCE_PUSH=false shift ;; --clean) CLEAN_BUILD=true shift ;; --echo-without-push) ECHO_WITHOUT_PUSH=true shift ;; -h|--help) usage ;; *) log_error "Unknown option: $1" usage ;; esac done log_info "Configuration:" log_info " Target: $TARGET_NAME" log_info " Build Documentation: $BUILD_DOCS" log_info " Force Push: $FORCE_PUSH" log_warning "This is the legacy manual deployment path. Documentation is deployed from CI on version tags and manual workflow runs." if [[ -n "$HOSTING_BASE_PATH" ]]; then log_info " Hosting Base Path: $HOSTING_BASE_PATH" fi # Check for required tools command -v git >/dev/null 2>&1 || { log_error "git is required but not installed. Aborting." exit 1 } # Build documentation if requested if [[ "$BUILD_DOCS" == true ]]; then log_info "Building documentation..." BUILD_SCRIPT="$SCRIPT_DIR/build-documentation.sh" if [[ ! -f "$BUILD_SCRIPT" ]]; then log_error "Build script not found: $BUILD_SCRIPT" exit 1 fi BUILD_ARGS=() BUILD_ARGS+=(--target "$TARGET_NAME") BUILD_ARGS+=(--minimum-access-level "$MINIMUM_ACCESS_LEVEL") if [[ -n "$HOSTING_BASE_PATH" ]]; then BUILD_ARGS+=(--hosting-base-path "$HOSTING_BASE_PATH") fi if [[ -n "$SOURCE_SERVICE" ]]; then BUILD_ARGS+=(--source-service "$SOURCE_SERVICE") BUILD_ARGS+=(--source-service-base-url "$SOURCE_SERVICE_BASE_URL") fi if [[ "$CLEAN_BUILD" == true ]]; then BUILD_ARGS+=(--clean) fi "$BUILD_SCRIPT" "${BUILD_ARGS[@]}" fi # Verify documentation output exists if [[ ! -d "$DOCC_OUTPUT_DIR" ]] || [[ -z "$(ls -A "$DOCC_OUTPUT_DIR" 2>/dev/null)" ]]; then log_error "Documentation output not found at: $DOCC_OUTPUT_DIR" log_error "Please build documentation first or run without --no-build" exit 1 fi log_info "Using documentation from: $DOCC_OUTPUT_DIR" # Deploy to GitHub Pages GH_PAGES_DIR="$REPO_ROOT/gh-pages" log_info "Preparing GitHub Pages deployment..." # Check if we're in a git repository if ! git rev-parse --git-dir > /dev/null 2>&1; then log_error "Not in a git repository. Cannot deploy to GitHub Pages." exit 1 fi # Store current branch CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) # Check if gh-pages branch exists if git show-ref --verify --quiet refs/heads/gh-pages; then log_info "Using existing gh-pages branch" git fetch origin gh-pages 2>/dev/null || true git worktree add "$GH_PAGES_DIR" gh-pages || { log_warning "Worktree already exists, removing and recreating..." git worktree remove "$GH_PAGES_DIR" --force git worktree add "$GH_PAGES_DIR" gh-pages } else log_info "Creating new gh-pages branch" # Create an empty orphan branch first git checkout --orphan gh-pages git rm -rf . 2>/dev/null || true git commit --allow-empty -m "Initialize gh-pages branch" git checkout "$CURRENT_BRANCH" # Now create worktree from the new branch git worktree add "$GH_PAGES_DIR" gh-pages fi # Copy documentation to gh-pages worktree docs folder log_info "Copying documentation files..." mkdir -p "$GH_PAGES_DIR/docs" rsync -av --delete "$DOCC_OUTPUT_DIR/" "$GH_PAGES_DIR/docs/" # Add .nojekyll to prevent GitHub Pages from processing with Jekyll touch "$GH_PAGES_DIR/.nojekyll" # Commit and push cd "$GH_PAGES_DIR" git add -Af . if git diff --cached --quiet; then log_info "No changes to documentation" else log_info "Committing documentation changes..." if [[ "$FORCE_PUSH" == true ]]; then # Use --amend to avoid accumulating commits with large binary files # Check if there are any commits in the branch if git rev-parse HEAD >/dev/null 2>&1; then git commit --amend -m "Update documentation (generated from $CURRENT_BRANCH@$(git -C "$REPO_ROOT" rev-parse --short HEAD))" else # First commit on the branch git commit -m "Update documentation (generated from $CURRENT_BRANCH@$(git -C "$REPO_ROOT" rev-parse --short HEAD))" fi log_info "Pushing to gh-pages branch..." log_info "Using --force to save git repo size (avoids accumulating large binary files)" git_push --force origin gh-pages else git commit -m "Update documentation (generated from $CURRENT_BRANCH@$(git -C "$REPO_ROOT" rev-parse --short HEAD))" log_info "Pushing to gh-pages branch..." git_push origin gh-pages fi log_info "${GREEN}✓${NC} Documentation published successfully!" log_info "GitHub Pages will be updated shortly at your repository's GitHub Pages URL" fi # Cleanup cd "$REPO_ROOT" git worktree remove "$GH_PAGES_DIR" log_info "Cleaning up build artifacts..." rm -rf "$DOCS_DIR" log_info "Done!"