Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions .github/workflows/mirror-repositories.yml
Original file line number Diff line number Diff line change
@@ -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"
132 changes: 132 additions & 0 deletions MIRRORING_SETUP.md
Original file line number Diff line number Diff line change
@@ -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
Loading