From 4169bee10f244631e46b8b66c26a755798e97f03 Mon Sep 17 00:00:00 2001 From: konard Date: Wed, 10 Sep 2025 18:31:47 +0300 Subject: [PATCH 1/3] Initial commit with task details for issue #82 Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: https://github.com/linksplatform/Interfaces/issues/82 --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f2f2d2c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/linksplatform/Interfaces/issues/82 +Your prepared branch: issue-82-4655482c +Your prepared working directory: /tmp/gh-issue-solver-1757518304046 + +Proceed. \ No newline at end of file From fb6d2932d999e366eb7541f856892298c2e4477e Mon Sep 17 00:00:00 2001 From: konard Date: Wed, 10 Sep 2025 18:32:05 +0300 Subject: [PATCH 2/3] Remove CLAUDE.md - PR created successfully --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index f2f2d2c..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/linksplatform/Interfaces/issues/82 -Your prepared branch: issue-82-4655482c -Your prepared working directory: /tmp/gh-issue-solver-1757518304046 - -Proceed. \ No newline at end of file From b32e2253eebb1344da2cc9237526fe7da0c30264 Mon Sep 17 00:00:00 2001 From: konard Date: Wed, 10 Sep 2025 18:34:51 +0300 Subject: [PATCH 3/3] Add automatic mirroring to GitLab and Bitbucket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implement comprehensive GitHub Actions workflow for repository mirroring - Add safe branch deletion handling (only if fully merged) - Include detailed setup documentation with security considerations - Support for both GitLab and Bitbucket with error handling - Maintain complete repository history across all mirrors Fixes #82 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/mirror-repositories.yml | 171 ++++++++++++++++++++++ MIRRORING_SETUP.md | 132 +++++++++++++++++ 2 files changed, 303 insertions(+) create mode 100644 .github/workflows/mirror-repositories.yml create mode 100644 MIRRORING_SETUP.md diff --git a/.github/workflows/mirror-repositories.yml b/.github/workflows/mirror-repositories.yml new file mode 100644 index 0000000..6e28b1c --- /dev/null +++ b/.github/workflows/mirror-repositories.yml @@ -0,0 +1,171 @@ +name: Mirror to GitLab and Bitbucket + +on: + push: + branches: ['*'] + tags: ['*'] + delete: + # Triggered when branches or tags are deleted + +env: + GITLAB_URL: gitlab.com + BITBUCKET_URL: bitbucket.org + +jobs: + mirror-to-gitlab: + runs-on: ubuntu-latest + if: github.event_name == 'push' + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch complete history for mirroring + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Git + run: | + git config --global user.name "GitHub Actions Mirror Bot" + git config --global user.email "actions@github.com" + + - name: Add GitLab remote and mirror + env: + GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} + GITLAB_PROJECT_PATH: ${{ secrets.GITLAB_PROJECT_PATH }} # e.g., linksplatform/Interfaces + run: | + # Add GitLab remote + git remote add gitlab https://oauth2:${GITLAB_TOKEN}@${GITLAB_URL}/${GITLAB_PROJECT_PATH}.git + + # Push all branches and tags to GitLab + git push --mirror gitlab || { + echo "Mirror push failed, attempting individual branch push" + git push gitlab ${GITHUB_REF#refs/heads/} || echo "Failed to push current branch" + } + + mirror-to-bitbucket: + runs-on: ubuntu-latest + if: github.event_name == 'push' + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch complete history for mirroring + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Git + run: | + git config --global user.name "GitHub Actions Mirror Bot" + git config --global user.email "actions@github.com" + + - name: Add Bitbucket remote and mirror + env: + BITBUCKET_USERNAME: ${{ secrets.BITBUCKET_USERNAME }} + BITBUCKET_APP_PASSWORD: ${{ secrets.BITBUCKET_APP_PASSWORD }} + BITBUCKET_PROJECT_PATH: ${{ secrets.BITBUCKET_PROJECT_PATH }} # e.g., linksplatform/interfaces + run: | + # Add Bitbucket remote + git remote add bitbucket https://${BITBUCKET_USERNAME}:${BITBUCKET_APP_PASSWORD}@${BITBUCKET_URL}/${BITBUCKET_PROJECT_PATH}.git + + # Push all branches and tags to Bitbucket + git push --mirror bitbucket || { + echo "Mirror push failed, attempting individual branch push" + git push bitbucket ${GITHUB_REF#refs/heads/} || echo "Failed to push current branch" + } + + handle-branch-deletion: + runs-on: ubuntu-latest + if: github.event_name == 'delete' && github.event.ref_type == 'branch' + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Git + run: | + git config --global user.name "GitHub Actions Mirror Bot" + git config --global user.email "actions@github.com" + + - name: Check if branch was fully merged before deletion + id: check-merged + env: + DELETED_BRANCH: ${{ github.event.ref }} + run: | + echo "Checking if branch '${DELETED_BRANCH}' was fully merged..." + + # Check if the branch was merged into main/master + MAIN_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@' || echo "main") + + # Get the last commit of the deleted branch from GitHub API + LAST_COMMIT=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/${{ github.repository }}/commits/${DELETED_BRANCH}" \ + | jq -r '.sha' 2>/dev/null || echo "") + + if [ -n "${LAST_COMMIT}" ] && [ "${LAST_COMMIT}" != "null" ]; then + # Check if the commit exists in the main branch + if git merge-base --is-ancestor "${LAST_COMMIT}" "origin/${MAIN_BRANCH}" 2>/dev/null; then + echo "Branch was fully merged - safe to delete from mirrors" + echo "should_delete=true" >> $GITHUB_OUTPUT + else + echo "Branch was NOT fully merged - skipping deletion from mirrors" + echo "should_delete=false" >> $GITHUB_OUTPUT + fi + else + echo "Could not determine merge status - skipping deletion for safety" + echo "should_delete=false" >> $GITHUB_OUTPUT + fi + + - name: Delete branch from GitLab mirror + if: steps.check-merged.outputs.should_delete == 'true' + env: + GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} + GITLAB_PROJECT_PATH: ${{ secrets.GITLAB_PROJECT_PATH }} + DELETED_BRANCH: ${{ github.event.ref }} + run: | + echo "Deleting branch '${DELETED_BRANCH}' from GitLab mirror..." + git remote add gitlab https://oauth2:${GITLAB_TOKEN}@${GITLAB_URL}/${GITLAB_PROJECT_PATH}.git + git push gitlab --delete "${DELETED_BRANCH}" || echo "Branch may not exist in GitLab or already deleted" + + - name: Delete branch from Bitbucket mirror + if: steps.check-merged.outputs.should_delete == 'true' + env: + BITBUCKET_USERNAME: ${{ secrets.BITBUCKET_USERNAME }} + BITBUCKET_APP_PASSWORD: ${{ secrets.BITBUCKET_APP_PASSWORD }} + BITBUCKET_PROJECT_PATH: ${{ secrets.BITBUCKET_PROJECT_PATH }} + DELETED_BRANCH: ${{ github.event.ref }} + run: | + echo "Deleting branch '${DELETED_BRANCH}' from Bitbucket mirror..." + git remote add bitbucket https://${BITBUCKET_USERNAME}:${BITBUCKET_APP_PASSWORD}@${BITBUCKET_URL}/${BITBUCKET_PROJECT_PATH}.git + git push bitbucket --delete "${DELETED_BRANCH}" || echo "Branch may not exist in Bitbucket or already deleted" + + mirror-tags: + runs-on: ubuntu-latest + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Git + run: | + git config --global user.name "GitHub Actions Mirror Bot" + git config --global user.email "actions@github.com" + + - name: Mirror tags to GitLab + env: + GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} + GITLAB_PROJECT_PATH: ${{ secrets.GITLAB_PROJECT_PATH }} + run: | + git remote add gitlab https://oauth2:${GITLAB_TOKEN}@${GITLAB_URL}/${GITLAB_PROJECT_PATH}.git + git push gitlab --tags || echo "Failed to push tags to GitLab" + + - name: Mirror tags to Bitbucket + env: + BITBUCKET_USERNAME: ${{ secrets.BITBUCKET_USERNAME }} + BITBUCKET_APP_PASSWORD: ${{ secrets.BITBUCKET_APP_PASSWORD }} + BITBUCKET_PROJECT_PATH: ${{ secrets.BITBUCKET_PROJECT_PATH }} + run: | + git remote add bitbucket https://${BITBUCKET_USERNAME}:${BITBUCKET_APP_PASSWORD}@${BITBUCKET_URL}/${BITBUCKET_PROJECT_PATH}.git + git push bitbucket --tags || echo "Failed to push tags to Bitbucket" \ No newline at end of file diff --git a/MIRRORING_SETUP.md b/MIRRORING_SETUP.md new file mode 100644 index 0000000..a459bc8 --- /dev/null +++ b/MIRRORING_SETUP.md @@ -0,0 +1,132 @@ +# Repository Mirroring Setup Guide + +This document explains how to set up automatic mirroring to GitLab and Bitbucket for the Interfaces repository. + +## Overview + +The mirroring system automatically: +- Mirrors all branch and tag pushes to GitLab and Bitbucket +- Safely handles branch deletions (only if fully merged) +- Provides backup and multi-platform accessibility +- Maintains complete repository history + +## Prerequisites + +### 1. GitLab Setup +1. Create a project on GitLab at `gitlab.com/linksplatform/interfaces` +2. Generate a Personal Access Token: + - Go to GitLab → User Settings → Access Tokens + - Create token with `api`, `read_repository`, and `write_repository` scopes + - Save the token securely + +### 2. Bitbucket Setup +1. Create a repository on Bitbucket at `bitbucket.org/linksplatform/interfaces` +2. Generate an App Password: + - Go to Bitbucket → Personal settings → App passwords + - Create password with `Repositories: Write` permission + - Save the password securely + +## Required GitHub Secrets + +Add the following secrets to your GitHub repository settings: + +### GitLab Secrets +- `GITLAB_TOKEN`: Your GitLab Personal Access Token +- `GITLAB_PROJECT_PATH`: `linksplatform/interfaces` (or your preferred path) + +### Bitbucket Secrets +- `BITBUCKET_USERNAME`: Your Bitbucket username +- `BITBUCKET_APP_PASSWORD`: Your Bitbucket App Password +- `BITBUCKET_PROJECT_PATH`: `linksplatform/interfaces` (or your preferred path) + +## How to Add Secrets + +1. Go to your GitHub repository +2. Navigate to Settings → Secrets and variables → Actions +3. Click "New repository secret" +4. Add each secret with the exact names listed above + +## Workflow Features + +### Automatic Mirroring +- **Push Events**: All branch and tag pushes are automatically mirrored +- **Full History**: Complete repository history is maintained +- **Error Handling**: Graceful fallbacks if mirror operations fail + +### Safe Branch Deletion +- **Merge Check**: Only deletes branches from mirrors if they were fully merged +- **Safety First**: Skips deletion if merge status cannot be determined +- **Main Branch Protection**: Checks against main/master branch for merge status + +### Tag Synchronization +- **All Tags**: Mirrors all repository tags to both platforms +- **Release Sync**: Keeps release tags in sync across all platforms + +## Monitoring + +### Workflow Status +- Check GitHub Actions tab for mirror workflow status +- Each platform (GitLab/Bitbucket) has separate jobs for better isolation +- Failed mirrors don't block other operations + +### Troubleshooting + +#### Common Issues +1. **Authentication Failures** + - Verify tokens/passwords are correct and not expired + - Check that secrets are properly named in GitHub + +2. **Repository Not Found** + - Ensure target repositories exist on GitLab/Bitbucket + - Verify project paths match the configured secrets + +3. **Permission Errors** + - Confirm GitLab token has required scopes + - Verify Bitbucket app password has write permissions + +#### Logs +Check the GitHub Actions logs for detailed error messages: +1. Go to Actions tab in your repository +2. Click on the failed workflow run +3. Expand the failed job to see error details + +## Manual Sync (Emergency) + +If automatic mirroring fails, you can manually sync: + +```bash +# Clone the repository +git clone https://github.com/linksplatform/Interfaces.git +cd Interfaces + +# Add remotes +git remote add gitlab https://oauth2:TOKEN@gitlab.com/linksplatform/interfaces.git +git remote add bitbucket https://USERNAME:PASSWORD@bitbucket.org/linksplatform/interfaces.git + +# Push everything +git push --mirror gitlab +git push --mirror bitbucket +``` + +## Security Considerations + +- Tokens and passwords are stored as encrypted GitHub secrets +- Workflow runs only have access to secrets during execution +- All authentication uses secure HTTPS connections +- Branch deletion safety checks prevent accidental data loss + +## Testing + +After setup, test the mirroring by: +1. Creating a test branch and pushing it +2. Verifying it appears on both GitLab and Bitbucket +3. Merging the branch and deleting it +4. Confirming it's removed from mirrors + +## Support + +For issues with this mirroring setup: +1. Check the workflow logs in GitHub Actions +2. Verify all secrets are correctly configured +3. Ensure target repositories exist and are accessible +4. Review this documentation for troubleshooting steps \ No newline at end of file