Skip to content

fix: rewrite sync-to-gh-pages using git clone instead of worktree #93

fix: rewrite sync-to-gh-pages using git clone instead of worktree

fix: rewrite sync-to-gh-pages using git clone instead of worktree #93

Workflow file for this run

# 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