fix: rewrite sync-to-gh-pages using git clone instead of worktree #93
Workflow file for this run
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
| # Main PPA workflow — lint & source sync | |
| # Triggers on pushes/PRs to main. Tests source, then syncs to gh-pages. | |
| name: PPA Main | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| submodules: true | |
| - name: Lint shell scripts | |
| run: | | |
| set -euo pipefail | |
| echo "Checking shell syntax..." | |
| find . -name "*.sh" -not -path "./.git/*" -print0 | while IFS= read -r -d '' file; do | |
| echo " Checking: $file" | |
| bash -n "$file" || exit 1 | |
| done | |
| echo "All shell scripts passed syntax check" | |
| - name: Lint YAML workflows | |
| run: | | |
| set -euo pipefail | |
| echo "Checking workflow YAML syntax..." | |
| for f in .github/workflows/*.yml; do | |
| echo " OK: $f" | |
| python3 -c "import yaml; yaml.safe_load(open('$f'))" || exit 1 | |
| done | |
| detect-changes: | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| outputs: | |
| packages: ${{ steps.detect.outputs.packages }} | |
| has_changes: ${{ steps.detect.outputs.has_changes }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| submodules: true | |
| - name: Detect changed submodules | |
| id: detect | |
| run: | | |
| set -euo pipefail | |
| SUBMODULES=$(git submodule status | awk '{print $2}' | grep '^src/diepxuan/' | sed 's|^src/diepxuan/||' | sed 's|/$||' | jq -R -s -c 'split("\n") | map(select(length > 0))') | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| echo "packages=$SUBMODULES" >> $GITHUB_OUTPUT | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "All packages will be built (manual trigger)" | |
| exit 0 | |
| fi | |
| BASE_REF="${{ github.base_ref }}" | |
| if [[ -z "$BASE_REF" ]]; then | |
| # Direct push to main (not a PR) — compare with previous commit | |
| CHANGES=$(git diff --name-only HEAD~1...HEAD 2>/dev/null || echo "") | |
| else | |
| # PR — compare with base branch | |
| CHANGES=$(git diff --name-only "origin/$BASE_REF...HEAD" 2>/dev/null || echo "") | |
| fi | |
| echo "Changes detected: $CHANGES" | |
| CHANGED_PACKAGES="[]" | |
| HAS_CHANGES="false" | |
| if [[ -n "$CHANGES" ]]; then | |
| for submodule in $(git submodule status | awk '{print $2}' | grep '^src/diepxuan/' | sed 's|^src/diepxuan/||' | sed 's|/$||'); do | |
| if echo "$CHANGES" | grep -q "^src/diepxuan/$submodule/"; then | |
| echo "Package '$submodule' has changes" | |
| CHANGED_PACKAGES=$(echo "$CHANGED_PACKAGES" | jq -c ". + [\"$submodule\"]") | |
| HAS_CHANGES="true" | |
| fi | |
| done | |
| fi | |
| if [[ "$CHANGED_PACKAGES" == "[]" ]]; then | |
| echo "No package changes detected" | |
| echo "packages=[]" >> $GITHUB_OUTPUT | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "packages=$CHANGED_PACKAGES" >> $GITHUB_OUTPUT | |
| echo "has_changes=$HAS_CHANGES" >> $GITHUB_OUTPUT | |
| echo "Will build: $CHANGED_PACKAGES" | |
| fi | |
| sync-to-gh-pages: | |
| runs-on: ubuntu-latest | |
| needs: [lint, detect-changes] | |
| if: github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout main | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: main | |
| fetch-depth: 1 | |
| submodules: true | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Sync to gh-pages | |
| run: | | |
| set -euo pipefail | |
| git config user.name "DiepXuan CI" | |
| git config user.email "ci@diepxuan.com" | |
| # Save submodule refs from main BEFORE switching branches | |
| declare -A SUBMODULE_REFS | |
| while IFS= read -r line; do | |
| path=$(echo "$line" | cut -d' ' -f2) | |
| ref=$(echo "$line" | cut -d' ' -f1) | |
| SUBMODULE_REFS["$path"]="$ref" | |
| done < <(git submodule foreach --quiet 'echo "$sha1 $sm_path"') | |
| # Also save .gitmodules content | |
| GITMODULES_CONTENT=$(cat .gitmodules) | |
| # Clone gh-pages into a separate directory (fresh checkout, not worktree) | |
| rm -rf _gh-pages-sync 2>/dev/null || true | |
| git clone --single-branch --branch gh-pages --depth=1 \ | |
| "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" \ | |
| _gh-pages-sync | |
| cd _gh-pages-sync | |
| git config user.name "DiepXuan CI" | |
| git config user.email "ci@diepxuan.com" | |
| # Remove all tracked non-generated files | |
| git rm -rf --ignore-unmatch \ | |
| AGENTS.md BOOTSTRAP.md SOUL.md IDENTITY.md USER.md TOOLS.md HEARTBEAT.md \ | |
| README.md .gitignore .gitmodules .editorconfig \ | |
| Dockerfile install.sh \ | |
| docs/ .github/ .openclaw/ .stfolder/ \ | |
| src/ conf/ \ | |
| 2>/dev/null || true | |
| # Copy source files from main | |
| cd .. | |
| cp README.md _gh-pages-sync/ | |
| cp .gitignore _gh-pages-sync/ | |
| cp .editorconfig _gh-pages-sync/ 2>/dev/null || true | |
| echo "$GITMODULES_CONTENT" > _gh-pages-sync/.gitmodules | |
| cd _gh-pages-sync | |
| # Initialize submodules | |
| git submodule sync | |
| git submodule update --init --force 2>/dev/null || true | |
| # Checkout each submodule to the correct ref from main | |
| cd .. | |
| for submodule_dir in src/diepxuan/*/; do | |
| name=$(basename "$submodule_dir") | |
| ref="${SUBMODULE_REFS[src/diepxuan/$name]:-}" | |
| [ -z "$ref" ] && continue | |
| wt_dir="_gh-pages-sync/src/diepxuan/$name" | |
| if [ -d "$wt_dir" ]; then | |
| (cd "$wt_dir" && git fetch origin 2>/dev/null && git checkout "$ref" 2>/dev/null) || true | |
| fi | |
| done | |
| # Add submodules to index | |
| cd _gh-pages-sync | |
| git add src/ 2>/dev/null || true | |
| # Sync conf directory | |
| cd .. | |
| rm -rf _gh-pages-sync/conf 2>/dev/null || true | |
| if [ -d conf ]; then | |
| cp -r conf _gh-pages-sync/conf | |
| fi | |
| cd _gh-pages-sync | |
| # Stage and commit | |
| git add -A | |
| if ! git diff --cached --quiet; then | |
| git commit -m "ci: sync source from main@${{ github.sha }}" | |
| git push origin gh-pages | |
| else | |
| echo "No changes to sync" | |
| fi | |
| # Cleanup | |
| cd .. | |
| rm -rf _gh-pages-sync |