Compare commits
7 Commits
50200abc0c
...
94d5e3d0f6
Author | SHA1 | Date | |
---|---|---|---|
![]() |
94d5e3d0f6 | ||
![]() |
ecd6b0d4cf | ||
![]() |
b30b4f158c | ||
![]() |
376471cd3a | ||
![]() |
d1b6ae381c | ||
![]() |
5e772c118e | ||
![]() |
8c741b5b7c |
66
.github/workflows/sync.yaml
vendored
Normal file
66
.github/workflows/sync.yaml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
# GitHub Actions workflow file to sync an external repository to this GitHub mirror.
|
||||
# This file was automatically generated by go-github-sync.
|
||||
#
|
||||
# The workflow does the following:
|
||||
# - Runs on a scheduled basis (and can also be triggered manually)
|
||||
# - Clones the GitHub mirror repository
|
||||
# - Fetches changes from the primary external repository
|
||||
# - Applies those changes to the mirror repository
|
||||
# - Pushes the updated content back to the GitHub mirror
|
||||
#
|
||||
# Authentication is handled by the GITHUB_TOKEN secret provided by GitHub Actions.
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate Github Actions Environment
|
||||
run: if [ "$GITHUB_ACTIONS" != "true" ]; then echo 'This script must be run in a GitHub Actions environment.'; exit 1; fi
|
||||
- name: Checkout GitHub Mirror
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Configure Git
|
||||
run: |-
|
||||
git config user.name 'GitHub Actions'
|
||||
git config user.email 'actions@github.com'
|
||||
- env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: Sync Primary Repository
|
||||
run: |-
|
||||
# Add the primary repository as a remote
|
||||
git remote add primary https://i2pgit.org/go-i2p/go-github-sync.git
|
||||
|
||||
# Fetch the latest changes from the primary repository
|
||||
git fetch primary
|
||||
|
||||
# Check if the primary branch exists in the primary repository
|
||||
if git ls-remote --heads primary main | grep -q main; then
|
||||
echo "Primary branch main found in primary repository"
|
||||
else
|
||||
echo "Error: Primary branch main not found in primary repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if we're already on the mirror branch
|
||||
if git rev-parse --verify --quiet main; then
|
||||
git checkout main
|
||||
else
|
||||
# Create the mirror branch if it doesn't exist
|
||||
git checkout -b main
|
||||
fi
|
||||
|
||||
|
||||
# Force-apply all changes from primary, overriding any conflicts
|
||||
echo "Performing force sync from primary/main to main"
|
||||
git reset --hard primary/main
|
||||
|
||||
|
||||
# Push changes back to the mirror repository
|
||||
git push origin main
|
||||
name: Sync Primary Repository to GitHub Mirror
|
||||
"on":
|
||||
push: {}
|
||||
schedule:
|
||||
- cron: 0 * * * *
|
||||
workflow_dispatch: {}
|
60
README.md
60
README.md
@@ -1,2 +1,60 @@
|
||||
# go-github-sync
|
||||
Automatically set up github sync
|
||||
|
||||
A Go tool that generates and sets up GitHub Actions workflows to automatically sync external repositories to GitHub mirrors.
|
||||
|
||||
## Overview
|
||||
|
||||
The `go-github-sync` tool creates GitHub Actions workflows that periodically pull changes from a primary repository and push them to a GitHub mirror repository. It can either output the workflow YAML file or directly set it up in the target GitHub repository.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/go-i2p/go-github-sync.git
|
||||
|
||||
# Build the tool
|
||||
cd go-github-sync
|
||||
go build -o github-sync ./cmd/github-sync
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Basic usage
|
||||
github-sync --primary https://example.org/repo.git --mirror https://github.com/user/repo
|
||||
|
||||
# Output workflow to file
|
||||
github-sync --primary https://example.org/repo.git --mirror https://github.com/user/repo --output workflow.yml
|
||||
|
||||
# Setup workflow in GitHub repository
|
||||
github-sync --primary https://example.org/repo.git --mirror https://github.com/user/repo --setup
|
||||
```
|
||||
|
||||
### Command Line Options
|
||||
|
||||
- `--primary`, `-p`: Primary repository URL (required)
|
||||
- `--mirror`, `-m`: GitHub mirror repository URL (required, auto-detected if possible)
|
||||
- `--primary-branch`: Primary repository branch name (default: "main")
|
||||
- `--mirror-branch`: GitHub mirror repository branch name (default: "main")
|
||||
- `--interval`, `-i`: Sync interval - hourly, daily, weekly (default: "hourly")
|
||||
- `--force`: Force sync by overwriting mirror with primary content (default: true)
|
||||
- `--output`, `-o`: Output file for workflow YAML (default: ".github/workflows/sync.yaml")
|
||||
- `--setup`: Automatically setup the workflow in the GitHub repository
|
||||
- `--verbose`, `-v`: Enable verbose logging
|
||||
|
||||
## Requirements
|
||||
|
||||
- GitHub token (needed when using `--setup` flag)
|
||||
- Set via `GITHUB_TOKEN` or `GH_TOKEN` environment variable
|
||||
|
||||
## Dependencies
|
||||
|
||||
- github.com/google/go-github/v61
|
||||
- github.com/spf13/cobra
|
||||
- go.uber.org/zap
|
||||
- golang.org/x/oauth2
|
||||
- gopkg.in/yaml.v3
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
@@ -4,6 +4,7 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -50,17 +51,16 @@ var (
|
||||
// AddFlags adds the configuration flags to the given command.
|
||||
func AddFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().StringVarP(&primaryRepo, "primary", "p", "", "Primary repository URL (required)")
|
||||
cmd.Flags().StringVarP(&mirrorRepo, "mirror", "m", "", "GitHub mirror repository URL (required)")
|
||||
cmd.Flags().StringVarP(&mirrorRepo, "mirror", "m", detectGithubRemote(), "GitHub mirror repository URL (required)")
|
||||
cmd.Flags().StringVar(&primaryBranch, "primary-branch", "main", "Primary repository branch name")
|
||||
cmd.Flags().StringVar(&mirrorBranch, "mirror-branch", "main", "GitHub mirror repository branch name")
|
||||
cmd.Flags().StringVarP(&syncInterval, "interval", "i", "hourly", "Sync interval (hourly, daily, weekly)")
|
||||
cmd.Flags().BoolVar(&forceSync, "force", true, "Force sync by overwriting mirror with primary content")
|
||||
cmd.Flags().StringVarP(&outputFile, "output", "o", "", "Output file for workflow YAML (writes to stdout if not specified)")
|
||||
cmd.Flags().StringVarP(&outputFile, "output", "o", ".github/workflows/sync.yaml", "Output file for workflow YAML (writes to stdout if not specified)")
|
||||
cmd.Flags().BoolVar(&setupWorkflow, "setup", false, "Automatically setup the workflow in the GitHub repository")
|
||||
cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose logging")
|
||||
|
||||
cmd.MarkFlagRequired("primary")
|
||||
cmd.MarkFlagRequired("mirror")
|
||||
}
|
||||
|
||||
// Load parses the flags and environment variables to build the configuration.
|
||||
@@ -106,3 +106,34 @@ func Load() (*Config, error) {
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// detectGithubRemote attempts to detect a GitHub remote URL from the current git repository
|
||||
func detectGithubRemote() string {
|
||||
// Execute git remote -v command
|
||||
cmd := exec.Command("git", "remote", "-v")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Parse the output to find GitHub remotes
|
||||
lines := strings.Split(string(output), "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "github.com") && strings.Contains(line, "(push)") {
|
||||
// Extract the GitHub repository URL
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) >= 2 {
|
||||
url := parts[1]
|
||||
// Convert SSH URL to HTTPS URL if needed
|
||||
if strings.HasPrefix(url, "git@github.com:") {
|
||||
url = strings.Replace(url, "git@github.com:", "https://github.com/", 1)
|
||||
}
|
||||
// Remove .git suffix if present
|
||||
url = strings.TrimSuffix(url, ".git")
|
||||
return url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
@@ -81,6 +81,7 @@ func generateWorkflowYAML(data WorkflowTemplate) (string, error) {
|
||||
workflow := map[string]interface{}{
|
||||
"name": "Sync Primary Repository to GitHub Mirror",
|
||||
"on": map[string]interface{}{
|
||||
"push": map[string]interface{}{},
|
||||
"schedule": []map[string]string{
|
||||
{"cron": data.CronSchedule},
|
||||
},
|
||||
@@ -90,6 +91,10 @@ func generateWorkflowYAML(data WorkflowTemplate) (string, error) {
|
||||
"sync": map[string]interface{}{
|
||||
"runs-on": "ubuntu-latest",
|
||||
"steps": []map[string]interface{}{
|
||||
{
|
||||
"name": "Validate Github Actions Environment",
|
||||
"run": "if [ \"$GITHUB_ACTIONS\" != \"true\" ]; then echo 'This script must be run in a GitHub Actions environment.'; exit 1; fi",
|
||||
},
|
||||
{
|
||||
"name": "Checkout GitHub Mirror",
|
||||
"uses": "actions/checkout@v3",
|
||||
|
Reference in New Issue
Block a user