From e7bf67b0821061b7f509e262e7bc0640a519d322 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 00:17:14 +0000 Subject: [PATCH 1/2] Initial plan From dee30b04c9210893b5aa9ec97dc9a6ff17aa1d82 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 00:22:14 +0000 Subject: [PATCH 2/2] docs: align repository with DPC conventions Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com> Agent-Logs-Url: https://github.com/dmccoystephenson/gh-backup/sessions/b24e176a-eb8f-4df9-a437-62e5d18f8d90 --- .github/copilot-instructions.md | 33 ++++++ .github/workflows/build.yml | 25 ++++ .github/workflows/release.yml | 29 +++++ CHANGELOG.md | 21 ++++ COMMANDS.md | 117 +++++++++++++++++++ CONFIG.md | 85 ++++++++++++++ CONTRIBUTING.md | 74 ++++++++++++ README.md | 197 ++++++++++---------------------- USER_GUIDE.md | 133 +++++++++++++++++++++ 9 files changed, 578 insertions(+), 136 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 COMMANDS.md create mode 100644 CONFIG.md create mode 100644 CONTRIBUTING.md create mode 100644 USER_GUIDE.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..6b4db45 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,33 @@ +# Copilot Instructions + +This repository follows the DPC (Dans Plugins Community) conventions defined at +https://github.com/Dans-Plugins/dpc-conventions. Read those conventions before +making any changes. + +## Technology Stack + +- Language: Java 17 +- Build tool: Maven +- Framework: Spring Boot 3 +- Key libraries: kohsuke/github-api, Eclipse JGit +- Test framework: JUnit 5 (via Spring Boot Test) + +## Project Structure + +- `src/main/java/com/github/backup/` – Core application classes (backup service, GitHub service, CLI runner) +- `src/main/java/com/github/backup/web/` – Spring MVC REST controller and request/response models for web mode +- `src/main/resources/` – `application.properties`, `application-web.properties`, and static web assets +- `src/test/java/` – Unit tests mirroring the main source tree + +## Coding Conventions + +- Follow the existing package structure (`com.github.backup`) when adding new classes. +- Configuration is loaded from `application.properties`; use `@Value` or `@ConfigurationProperties` for new options. +- All new configuration options must be documented in `CONFIG.md`. +- User-facing documentation changes must be included in the same pull request as the related code change. + +## Contribution Workflow + +- Branch from `develop` for all changes. +- Open a pull request against `develop`, not `main`. +- Reference the related GitHub issue in every pull request description. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..83d7fe6 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,25 @@ +name: Build + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Build with Maven + run: mvn clean verify diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7eb5c67 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +name: Release + +on: + release: + types: [ created ] + +permissions: + contents: write + +jobs: + build-and-attach: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Build with Maven + run: mvn clean package + + - name: Upload JAR to release + uses: softprops/action-gh-release@v2 + with: + files: target/gh-backup-*.jar diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2e80967 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## [Unreleased] + +## [1.0.0] – 2026-01-01 + +### Added + +- CLI mode: back up public repositories for one or more GitHub users or organizations by passing their names as arguments +- Interactive mode (`-i` flag): prompt-based interface with `backup`, `status`, and `exit` commands +- Web UI mode (`-Dspring.profiles.active=web`): browser-based interface for managing backups +- REST API endpoints (`POST /api/backup`, `GET /api/status`) for programmatic access +- GitHub authentication via `GITHUB_TOKEN` environment variable for higher API rate limits +- Configurable backup directory via `backup.directory` system property (defaults to `~/gh-backups/`) +- Cross-platform path normalization (Linux, macOS, Windows) +- Parallel backup of multiple users and organizations +- Incremental updates: existing repositories are updated with `git fetch` instead of re-cloned diff --git a/COMMANDS.md b/COMMANDS.md new file mode 100644 index 0000000..29b8360 --- /dev/null +++ b/COMMANDS.md @@ -0,0 +1,117 @@ +# Commands Reference + +gh-backup is invoked from the command line via the built JAR. This document lists all supported arguments and modes. + +## Basic Syntax + +``` +java [JVM_OPTIONS] -jar target/gh-backup-1.0.0.jar [OPTIONS] [USER/ORG...] +``` + +## Positional Arguments + +### ` [user/org2] ...` + +**Description:** One or more GitHub usernames or organization names whose public repositories should be backed up. +**Required:** Yes (unless using interactive mode or web mode) +**Example:** +```bash +java -jar target/gh-backup-1.0.0.jar octocat github spring-projects +``` + +## Options + +### `-i` – Interactive Mode + +**Description:** Start the tool in interactive mode, providing a prompt for issuing commands without restarting the application. +**Usage:** +```bash +java -jar target/gh-backup-1.0.0.jar -i +``` + +### Interactive Mode Commands + +Once in interactive mode, the following commands are available at the `>` prompt: + +| Command | Description | +|---------|-------------| +| `backup ` | Back up all public repositories for the given GitHub user or organization | +| `status` | Display the backup directory path and a summary of all backed-up repositories | +| `exit` | Exit interactive mode and terminate the application | + +## JVM System Properties + +These are passed with `-D` before the `-jar` flag. + +### `-Dbackup.directory=` + +**Description:** Override the directory where repositories are saved. +**Default:** `~/gh-backups/` (the `gh-backups` folder in the current user's home directory) +**Example:** +```bash +java -Dbackup.directory=/mnt/storage/github-backups -jar target/gh-backup-1.0.0.jar octocat +``` + +### `-Dspring.profiles.active=web` + +**Description:** Start the application as a web server instead of a CLI tool. +**Default:** CLI mode +**Example:** +```bash +java -Dspring.profiles.active=web -jar target/gh-backup-1.0.0.jar +``` + +### `-Dserver.port=` + +**Description:** Set the HTTP port for the web server (only effective in web mode). +**Default:** `8080` +**Example:** +```bash +java -Dspring.profiles.active=web -Dserver.port=9000 -jar target/gh-backup-1.0.0.jar +``` + +## Environment Variables + +### `GITHUB_TOKEN` + +**Description:** A GitHub personal access token used to authenticate API requests. Increases the API rate limit from 60 to 5,000 requests per hour. +**Required:** No +**Example:** +```bash +export GITHUB_TOKEN=ghp_yourTokenHere +java -jar target/gh-backup-1.0.0.jar octocat +``` + +## Web API Endpoints + +When running in web mode (`-Dspring.profiles.active=web`), the following REST endpoints are available: + +| Method | Path | Description | +|--------|------|-------------| +| `POST` | `/api/backup` | Start a backup for a given user or organization | +| `GET` | `/api/status` | Return backup status and a list of all backed-up repositories | + +### POST /api/backup + +**Request body:** +```json +{ "username": "octocat" } +``` + +**Response:** +```json +{ "message": "Backup completed for octocat", "repositoryCount": 8 } +``` + +### GET /api/status + +**Response:** +```json +{ + "backupDirectory": "/home/user/gh-backups", + "users": ["octocat"], + "repositories": [ + { "name": "Hello-World", "owner": "octocat", "lastUpdated": "2026-01-10T12:30:45" } + ] +} +``` diff --git a/CONFIG.md b/CONFIG.md new file mode 100644 index 0000000..c7b551d --- /dev/null +++ b/CONFIG.md @@ -0,0 +1,85 @@ +# Configuration Guide + +Configuration is provided through Spring Boot property files and JVM system properties. + +The main configuration file is `src/main/resources/application.properties`. Values can be overridden at runtime with `-D=`. + +--- + +## backup.directory + +**Type:** string (file path) +**Default:** `${user.home}/gh-backups` +**Description:** The directory where cloned repositories are stored. The path is resolved relative to the user's home directory by default and is normalized for cross-platform compatibility (Linux, macOS, Windows). + +**Override at runtime:** +```bash +java -Dbackup.directory=/mnt/storage/github-backups -jar target/gh-backup-1.0.0.jar octocat +``` + +Windows example: +```bat +java -Dbackup.directory=C:\Backups\GitHub -jar target/gh-backup-1.0.0.jar octocat +``` + +--- + +## backup.mode + +**Type:** string (`cli` | `web`) +**Default:** `cli` +**Description:** Controls whether the application runs as a command-line tool (`cli`) or as a web server (`web`). Use `web` by activating the `web` Spring profile. + +**Override at runtime:** +```bash +java -Dspring.profiles.active=web -jar target/gh-backup-1.0.0.jar +``` + +The `web` profile (`application-web.properties`) automatically sets `backup.mode=web` and enables the servlet web application type. + +--- + +## spring.main.web-application-type + +**Type:** string (`none` | `servlet`) +**Default:** `none` (CLI mode) +**Description:** Spring Boot property that controls whether an embedded web server is started. Set to `servlet` when using web mode. Managed automatically by the `web` Spring profile. + +--- + +## server.port + +**Type:** integer +**Default:** `8080` +**Description:** The HTTP port on which the web server listens. Only effective when running in web mode. + +**Override at runtime:** +```bash +java -Dspring.profiles.active=web -Dserver.port=9000 -jar target/gh-backup-1.0.0.jar +``` + +--- + +## logging.level.com.github.backup + +**Type:** string (log level) +**Default:** `INFO` +**Description:** Log level for application classes. Increase to `DEBUG` for verbose output during troubleshooting. + +**Override at runtime:** +```bash +java -Dlogging.level.com.github.backup=DEBUG -jar target/gh-backup-1.0.0.jar octocat +``` + +--- + +## GITHUB_TOKEN (environment variable) + +**Type:** string +**Default:** not set +**Description:** A GitHub personal access token used to authenticate GitHub API requests. When set, the rate limit increases from 60 to 5,000 requests per hour. Not set via `application.properties`; pass it as an environment variable. + +```bash +export GITHUB_TOKEN=ghp_yourTokenHere +java -jar target/gh-backup-1.0.0.jar octocat +``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ab21613 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contributing + +## Thank You + +Thank you for your interest in contributing to gh-backup! This guide will help you get started. + +## Links + +- [Website](https://dansplugins.com) +- [Discord](https://discord.gg/xXtuAQ2) + +## Requirements + +- A GitHub account +- Git installed on your local machine +- Java 17 or higher +- Maven 3.6 or higher +- A Java IDE or text editor + +## Getting Started + +1. [Sign up for GitHub](https://github.com/signup) if you don't have an account. +2. Fork the repository by clicking **Fork** at the top right of the repo page. +3. Clone your fork: + ```bash + git clone https://github.com//gh-backup.git + ``` +4. Open the project in your IDE. +5. Build the project: + ```bash + mvn clean package + ``` + If you encounter errors, please open an issue. + +## Identifying What to Work On + +### Issues + +Work items are tracked as [GitHub issues](https://github.com/dmccoystephenson/gh-backup/issues). + +### Milestones + +Issues are grouped into [milestones](https://github.com/dmccoystephenson/gh-backup/milestones) representing upcoming releases. + +## Making Changes + +1. Make sure an issue exists for the work. If not, create one. +2. Switch to the `develop` branch: `git checkout develop` +3. Create a feature branch: `git checkout -b ` +4. Make your changes. +5. Test your changes (see [Testing](#testing)). +6. Commit: `git commit -m "Brief description of changes"` +7. Push to your fork: `git push origin ` +8. Open a pull request against the `develop` branch of the upstream repository. Include a description and link the related issue using `#`. +9. Address any review feedback. +10. Once approved, the maintainer will merge the PR into `develop`. + +## Testing + +Run the unit tests with: + +Linux / macOS: +```bash +mvn clean test +``` + +Windows: +```bat +mvn clean test +``` + +## Questions + +Ask in the [Discord server](https://discord.gg/xXtuAQ2). diff --git a/README.md b/README.md index 858d40c..aa3e9a7 100644 --- a/README.md +++ b/README.md @@ -1,178 +1,103 @@ # gh-backup -A tool built with Spring Boot to backup public GitHub repositories for specified users or organizations. Available as both a command-line tool and a web application. +## Description -## Features - -- **Web UI** for easy backup management through your browser -- Backup all public repositories from one or more GitHub users/organizations -- Clone new repositories or update existing ones -- **Interactive mode** for easier management and status viewing -- Support for authenticated and anonymous GitHub API access -- Parallel backup of multiple users/organizations -- Organized backup structure by user/organization - -## Prerequisites - -- Java 17 or higher -- Maven 3.6+ (for building from source) -- Git (for cloning repositories) +gh-backup is a Spring Boot tool for backing up public GitHub repositories for specified users or organizations. It is available as both a command-line tool and a web application. ## Installation -### Building from Source - -```bash -git clone https://github.com/dmccoystephenson/gh-backup.git -cd gh-backup -mvn clean package -``` +### First Time Installation -The executable JAR will be created at `target/gh-backup-1.0.0.jar` +1. Ensure [Java 17+](https://adoptium.net/) and [Maven 3.6+](https://maven.apache.org/) are installed. +2. Clone the repository: + ```bash + git clone https://github.com/dmccoystephenson/gh-backup.git + cd gh-backup + ``` +3. Build the project: + ```bash + mvn clean package + ``` +4. The executable JAR will be created at `target/gh-backup-1.0.0.jar`. ## Usage -### Web UI Mode (Recommended) +### Documentation -Start the web server: +- [User Guide](USER_GUIDE.md) – Getting started and common scenarios +- [Commands Reference](COMMANDS.md) – Complete list of all CLI commands and options +- [Configuration Guide](CONFIG.md) – Detailed configuration options -```bash -java -Dspring.profiles.active=web -jar target/gh-backup-1.0.0.jar -``` - -Then open your browser and navigate to `http://localhost:8080` to access the web interface. +## Support -The web UI allows you to: -- Create new backups by entering a GitHub user or organization name -- View the status of all your backups -- See a list of all backed up repositories with their last update times +You can find the support Discord server [here](https://discord.gg/xXtuAQ2). -To use a custom port: -```bash -java -Dspring.profiles.active=web -Dserver.port=9000 -jar target/gh-backup-1.0.0.jar -``` +### Experiencing a bug? -### Interactive Mode +Please fill out a bug report [here](https://github.com/dmccoystephenson/gh-backup/issues/new). -Start the tool in interactive mode for easier management: +- [Known Bugs](https://github.com/dmccoystephenson/gh-backup/issues?q=is%3Aissue+is%3Aopen+label%3Abug) -```bash -java -jar target/gh-backup-1.0.0.jar -i -``` - -In interactive mode, you can: -- Type `backup ` to backup a user or organization's repositories -- Type `status` to view current backup status and list all backed up repositories -- Type `exit` to quit - -Example session: -``` -> backup octocat -Fetching repositories for: octocat -Found 8 public repositories -... - -> status -Backup Status -============= -Backup directory: /path/to/backups - -octocat/ (8 repositories) - - Hello-World (last updated: 2026-01-10 12:30:45) - - Spoon-Knife (last updated: 2026-01-10 12:30:47) - ... - -Total: 1 users/organizations, 8 repositories - -> exit -Exiting interactive mode... -``` +## Contributing -### Basic Usage +- [CONTRIBUTING.md](CONTRIBUTING.md) -Backup repositories for one or more users/organizations: +## Testing -```bash -java -jar target/gh-backup-1.0.0.jar [user/org2] ... -``` +### Unit Tests -### Examples - -Backup repositories from a single user: -```bash -java -jar target/gh-backup-1.0.0.jar octocat -``` +Linux / macOS: -Backup repositories from multiple users/organizations: ```bash -java -jar target/gh-backup-1.0.0.jar octocat github spring-projects +mvn clean test ``` -### Using GitHub Authentication - -For higher rate limits and access to more API features, set the `GITHUB_TOKEN` environment variable: +Windows: -```bash -export GITHUB_TOKEN=your_github_token_here -java -jar target/gh-backup-1.0.0.jar octocat +```bat +mvn clean test ``` -To create a GitHub personal access token: -1. Go to GitHub Settings → Developer settings → Personal access tokens -2. Click "Generate new token" -3. Select scopes (public_repo is sufficient for public repositories) -4. Copy the generated token - -### Custom Backup Directory - -By default, repositories are backed up to `~/gh-backups/` (user home directory). This works on both Linux and Windows. To use a custom location: +If you see `BUILD SUCCESS`, the tests have passed. -```bash -java -Dbackup.directory=/path/to/backup -jar target/gh-backup-1.0.0.jar octocat -``` - -Windows example: -```bash -java -Dbackup.directory=C:\Backups\GitHub -jar target/gh-backup-1.0.0.jar octocat -``` +## Development -The backup directory path is automatically converted to an absolute path and normalized for cross-platform compatibility. +### Building and Running Locally -## Output Structure +1. Clone the repository and build: + ```bash + mvn clean package + ``` +2. Run in CLI mode: + ```bash + java -jar target/gh-backup-1.0.0.jar octocat + ``` +3. Run in web mode: + ```bash + java -Dspring.profiles.active=web -jar target/gh-backup-1.0.0.jar + ``` + Then open `http://localhost:8080` in your browser. -Repositories are organized by user/organization in the backup directory: +## Authors and Acknowledgement -``` -~/gh-backups/ -├── octocat/ -│ ├── Hello-World/ -│ ├── Spoon-Knife/ -│ └── ... -├── github/ -│ ├── docs/ -│ ├── roadmap/ -│ └── ... -└── ... -``` +### Developers -## How It Works +| Name | Main Contributions | +|------|--------------------| +| dmccoystephenson | Initial development and maintenance | -1. The tool connects to the GitHub API (authenticated or anonymously) -2. For each specified user/organization, it fetches all public repositories -3. Each repository is cloned to the local backup directory -4. If a repository already exists, it is updated with `git fetch` +## License -## Rate Limits +This project is licensed under the [MIT License](LICENSE). -- **Anonymous**: 60 requests per hour -- **Authenticated**: 5,000 requests per hour +You are free to use, modify, and distribute this software under the terms of the MIT License. -Using authentication is recommended for backing up users/organizations with many repositories. +See the [LICENSE](LICENSE) file for the full license text. -## License +## Project Status -This project is open source and available under the MIT License. +This project is in active development. -## Contributing +### Changelog -Contributions are welcome! Please feel free to submit a Pull Request. \ No newline at end of file +See [CHANGELOG.md](CHANGELOG.md) for a release-by-release summary of changes. \ No newline at end of file diff --git a/USER_GUIDE.md b/USER_GUIDE.md new file mode 100644 index 0000000..b41ffac --- /dev/null +++ b/USER_GUIDE.md @@ -0,0 +1,133 @@ +# User Guide + +## Prerequisites + +- Java 17 or higher installed on your system +- Git installed on your system (required for cloning repositories) +- A GitHub personal access token (optional, but recommended for higher API rate limits) + +## First Steps + +After building the project (`mvn clean package`), you can start backing up GitHub repositories immediately. + +### Quick Start – CLI Mode + +Back up all public repositories of a GitHub user or organization: + +```bash +java -jar target/gh-backup-1.0.0.jar octocat +``` + +Repositories will be saved to `~/gh-backups/` by default. + +### Quick Start – Web UI Mode + +Start the web server: + +```bash +java -Dspring.profiles.active=web -jar target/gh-backup-1.0.0.jar +``` + +Open `http://localhost:8080` in your browser to use the web interface. + +## Common Scenarios + +### Backing up a single user or organization + +```bash +java -jar target/gh-backup-1.0.0.jar octocat +``` + +### Backing up multiple users or organizations at once + +```bash +java -jar target/gh-backup-1.0.0.jar octocat github spring-projects +``` + +### Using GitHub authentication for higher rate limits + +Set the `GITHUB_TOKEN` environment variable before running: + +```bash +export GITHUB_TOKEN=your_github_token_here +java -jar target/gh-backup-1.0.0.jar octocat +``` + +To create a token: GitHub Settings → Developer settings → Personal access tokens → Generate new token. The `public_repo` scope is sufficient for public repositories. + +### Using a custom backup directory + +```bash +java -Dbackup.directory=/path/to/backup -jar target/gh-backup-1.0.0.jar octocat +``` + +Windows example: +```bat +java -Dbackup.directory=C:\Backups\GitHub -jar target/gh-backup-1.0.0.jar octocat +``` + +### Using interactive mode + +Start in interactive mode for an on-screen menu: + +```bash +java -jar target/gh-backup-1.0.0.jar -i +``` + +Available interactive commands: + +| Command | Description | +|---------|-------------| +| `backup ` | Back up all public repositories for the specified user or organization | +| `status` | Show the backup directory, number of users/organizations, and a list of all backed up repositories | +| `exit` | Quit the interactive session | + +### Example interactive session + +``` +> backup octocat +Fetching repositories for: octocat +Found 8 public repositories +... + +> status +Backup Status +============= +Backup directory: /home/user/gh-backups + +octocat/ (8 repositories) + - Hello-World (last updated: 2026-01-10 12:30:45) + - Spoon-Knife (last updated: 2026-01-10 12:30:47) + ... + +Total: 1 users/organizations, 8 repositories + +> exit +Exiting interactive mode... +``` + +## Output Structure + +Repositories are organized by user or organization inside the backup directory: + +``` +~/gh-backups/ +├── octocat/ +│ ├── Hello-World/ +│ ├── Spoon-Knife/ +│ └── ... +└── github/ + ├── docs/ + └── roadmap/ +``` + +Each subdirectory is a full Git repository. If a repository already exists on disk, running the tool again will update it with `git fetch`. + +## Rate Limits + +| Access type | Limit | +|-------------|-------| +| Anonymous | 60 requests per hour | +| Authenticated (token) | 5,000 requests per hour | + +Using a GitHub token is strongly recommended when backing up users or organizations with many repositories.