Sync CMP Directories #21
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: Sync CMP Directories | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| upstream: | |
| description: 'Upstream repository to sync directories from' | |
| default: 'https://github.com/openMF/kmp-project-template.git' | |
| required: true | |
| type: string | |
| schedule: | |
| - cron: '0 0 * * 1' | |
| jobs: | |
| sync-directories: | |
| if: github.repository != 'openMF/kmp-project-template' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: dev | |
| - name: Setup Git config | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Add upstream remote and fetch | |
| run: | | |
| set -euo pipefail | |
| UPSTREAM="${{ inputs.upstream || 'https://github.com/openMF/kmp-project-template.git' }}" | |
| git remote add upstream "$UPSTREAM" || true | |
| git fetch upstream || exit 1 | |
| - name: Check upstream/dev exists | |
| run: | | |
| set -euo pipefail | |
| if ! git rev-parse --verify upstream/dev >/dev/null 2>&1; then | |
| echo "Error: upstream/dev branch does not exist" | |
| exit 1 | |
| fi | |
| - name: Create and checkout temporary branch | |
| run: | | |
| set -euo pipefail | |
| TEMP_BRANCH="temp-sync-branch-${{ github.run_number }}" | |
| git checkout -b "$TEMP_BRANCH" upstream/dev || exit 1 | |
| echo "TEMP_BRANCH=$TEMP_BRANCH" >> $GITHUB_ENV | |
| - name: Sync directories and files | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Declare directories and files to sync | |
| DIRS=( | |
| "cmp-desktop" | |
| "cmp-web" | |
| "cmp-shared" | |
| "core-base" | |
| "build-logic" | |
| "fastlane" | |
| "fastlane-config" | |
| "scripts" | |
| "config" | |
| ".github" | |
| ".run" | |
| ) | |
| FILES=( | |
| "Gemfile" | |
| "Gemfile.lock" | |
| "ci-prepush.bat" | |
| "ci-prepush.sh" | |
| ) | |
| # Define exclusions | |
| declare -A EXCLUSIONS=( | |
| ["cmp-web"]="src/jsMain/resources src/wasmJsMain/resources" | |
| ["cmp-desktop"]="icons build.gradle.kts" | |
| ["fastlane-config"]="project_config.rb extract_config.rb" | |
| [".github"]="workflows/sync-dirs.yaml" | |
| ["root"]="secrets.env" | |
| ) | |
| # Function to check if path should be excluded | |
| should_exclude() { | |
| local dir=$1 | |
| local path=$2 | |
| # Check for root exclusions (when dir is "." or "root") | |
| if [[ "$dir" == "." || "$dir" == "root" ]] && [[ -v "EXCLUSIONS[root]" ]]; then | |
| local root_excluded_paths | |
| IFS=' ' read -ra root_excluded_paths <<< "${EXCLUSIONS[root]}" | |
| for excluded in "${root_excluded_paths[@]}"; do | |
| if [[ "$path" == *"$excluded"* ]]; then | |
| return 0 | |
| fi | |
| done | |
| fi | |
| # Check directory-specific exclusions | |
| if [[ -v "EXCLUSIONS[$dir]" ]]; then | |
| local excluded_paths | |
| IFS=' ' read -ra excluded_paths <<< "${EXCLUSIONS[$dir]}" | |
| for excluded in "${excluded_paths[@]}"; do | |
| if [[ "$path" == *"$excluded"* ]]; then | |
| return 0 | |
| fi | |
| done | |
| fi | |
| return 1 | |
| } | |
| # Function to preserve excluded paths | |
| preserve_excluded() { | |
| local dir=$1 | |
| if [[ -v "EXCLUSIONS[$dir]" ]]; then | |
| local excluded_paths | |
| IFS=' ' read -ra excluded_paths <<< "${EXCLUSIONS[$dir]}" | |
| for excluded in "${excluded_paths[@]}"; do | |
| local full_path="$dir/$excluded" | |
| if [[ -e "$full_path" ]]; then | |
| echo "Preserving excluded path: $full_path" | |
| local temp_path="temp_excluded/$full_path" | |
| mkdir -p "$(dirname "$temp_path")" | |
| cp -r "$full_path" "$(dirname "$temp_path")/" | |
| fi | |
| done | |
| fi | |
| } | |
| # Function to restore excluded paths | |
| restore_excluded() { | |
| local dir=$1 | |
| if [[ -v "EXCLUSIONS[$dir]" ]]; then | |
| local excluded_paths | |
| IFS=' ' read -ra excluded_paths <<< "${EXCLUSIONS[$dir]}" | |
| for excluded in "${excluded_paths[@]}"; do | |
| local full_path="$dir/$excluded" | |
| local temp_path="temp_excluded/$full_path" | |
| if [[ -e "$temp_path" ]]; then | |
| echo "Restoring excluded path: $full_path" | |
| mkdir -p "$(dirname "$full_path")" | |
| rm -rf "$full_path" | |
| cp -r "$temp_path" "$(dirname "$full_path")/" | |
| fi | |
| done | |
| fi | |
| } | |
| # Function to preserve root-level excluded files | |
| preserve_root_files() { | |
| if [[ -v "EXCLUSIONS[root]" ]]; then | |
| local excluded_paths | |
| IFS=' ' read -ra excluded_paths <<< "${EXCLUSIONS[root]}" | |
| for excluded in "${excluded_paths[@]}"; do | |
| if [[ -e "$excluded" ]]; then | |
| echo "Preserving root-level excluded file: $excluded" | |
| mkdir -p "temp_excluded/root" | |
| cp -r "$excluded" "temp_excluded/root/" | |
| fi | |
| done | |
| fi | |
| } | |
| # Function to restore root-level excluded files | |
| restore_root_files() { | |
| if [[ -v "EXCLUSIONS[root]" ]]; then | |
| local excluded_paths | |
| IFS=' ' read -ra excluded_paths <<< "${EXCLUSIONS[root]}" | |
| for excluded in "${excluded_paths[@]}"; do | |
| if [[ -e "temp_excluded/root/$excluded" ]]; then | |
| echo "Restoring root-level excluded file: $excluded" | |
| cp -r "temp_excluded/root/$excluded" "./" | |
| fi | |
| done | |
| fi | |
| } | |
| # Create temp directory for exclusions | |
| mkdir -p temp_excluded | |
| # Preserve root-level exclusions before sync | |
| preserve_root_files | |
| # Switch to dev branch | |
| git checkout dev | |
| # Sync directories | |
| for dir in "${DIRS[@]}"; do | |
| if [[ ! -d "$dir" ]]; then | |
| echo "Creating $dir..." | |
| mkdir -p "$dir" | |
| fi | |
| # Preserve excluded paths before sync | |
| if [[ -d "$dir" ]]; then | |
| preserve_excluded "$dir" | |
| fi | |
| echo "Syncing $dir..." | |
| if ! git checkout "${{ env.TEMP_BRANCH }}" -- "$dir" 2>/dev/null; then | |
| echo "Warning: Could not sync directory $dir (may not exist in upstream)" | |
| fi | |
| # Restore excluded paths after sync | |
| restore_excluded "$dir" | |
| done | |
| # Sync files | |
| for file in "${FILES[@]}"; do | |
| file_dir=$(dirname "$file") | |
| file_name=$(basename "$file") | |
| # Check root exclusions for root-level files | |
| if [[ "$file_dir" == "." ]]; then | |
| if should_exclude "root" "$file_name"; then | |
| echo "Skipping excluded file: $file" | |
| continue | |
| fi | |
| elif should_exclude "$file_dir" "$file"; then | |
| echo "Skipping excluded file: $file" | |
| continue | |
| fi | |
| echo "Syncing $file..." | |
| if ! git checkout "${{ env.TEMP_BRANCH }}" -- "$file" 2>/dev/null; then | |
| echo "Warning: Could not sync file $file (may not exist in upstream)" | |
| fi | |
| done | |
| # Restore root-level excluded files | |
| restore_root_files | |
| # Cleanup temp directory | |
| rm -rf temp_excluded | |
| echo "Sync completed successfully!" | |
| - name: Clean up temporary branch | |
| if: always() | |
| run: git branch -D "${{ env.TEMP_BRANCH }}" 2>/dev/null || true | |
| - name: Check for changes | |
| id: check_changes | |
| run: | | |
| if [[ -n "$(git status --porcelain)" ]]; then | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "Changes detected:" | |
| git status --short | |
| else | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| echo "No changes detected" | |
| fi | |
| - name: Create Pull Request | |
| if: steps.check_changes.outputs.has_changes == 'true' | |
| uses: peter-evans/create-pull-request@v7 | |
| with: | |
| token: ${{ secrets.PAT_TOKEN }} | |
| commit-message: "chore: Sync directories and files from upstream" | |
| title: "chore: Sync directories and files from upstream" | |
| body: | | |
| Automated sync of directories and files from upstream repository. | |
| Changes included in this sync: | |
| **Directories:** | |
| - cmp-desktop (excluding icons, build.gradle.kts) | |
| - cmp-web (excluding src/jsMain/resources, src/wasmJsMain/resources) | |
| - cmp-shared | |
| - core-base | |
| - build-logic | |
| - fastlane | |
| - fastlane-config (excluding project_config.rb, extract_config.rb) | |
| - scripts | |
| - config | |
| - .github (excluding workflows/sync-dirs.yaml) | |
| - .run | |
| **Files:** | |
| - Gemfile | |
| - Gemfile.lock | |
| - ci-prepush.bat | |
| - ci-prepush.sh | |
| **Root-level exclusions:** | |
| - secrets.env | |
| --- | |
| Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| branch: sync-dirs-${{ github.run_number }} | |
| delete-branch: true | |
| labels: | | |
| sync | |
| automated pr | |
| base: dev |