From 867ece014a79442a4faa3e941ab6e545b0247079 Mon Sep 17 00:00:00 2001 From: Yorgei Date: Sat, 30 Aug 2025 20:11:34 +1000 Subject: [PATCH] a --- .dockerignore | 24 ++++++++ .env | 12 ++++ Dockerfile | 17 +++++ README.md | 103 +++++++++++++++++++++++++++++++ docker-compose.yml | 14 +++++ download_and_compare.py | 133 ++++++++++++++++++++++++++++++++++++++++ env.example | 12 ++++ requirements.txt | 2 + 8 files changed, 317 insertions(+) create mode 100644 .dockerignore create mode 100644 .env create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml create mode 100644 download_and_compare.py create mode 100644 env.example create mode 100644 requirements.txt diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b38e409 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,24 @@ +.git +.env +*.diff +*.json +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +env +pip-log.txt +pip-delete-this-directory.txt +.tox +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.log +.git +.mypy_cache +.pytest_cache +.hypothesis diff --git a/.env b/.env new file mode 100644 index 0000000..ddb0ec7 --- /dev/null +++ b/.env @@ -0,0 +1,12 @@ +GIT_REPO_URL=https://github.com/yourusername/yourrepo.git +GIT_USERNAME=yourusername +GIT_EMAIL=your.email@example.com +GIT_BRANCH=main + +# GitHub Authentication (choose one method): +# Method 1: Personal Access Token (recommended for HTTPS) +GITHUB_TOKEN=ghp_your_personal_access_token_here + +# Method 2: SSH Key (for SSH URLs) +# GIT_REPO_URL=git@github.com:yourusername/yourrepo.git +# SSH_PRIVATE_KEY_PATH=/path/to/your/private/key diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..03f68f5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.11-slim + +RUN apt-get update && apt-get install -y \ + git \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +RUN git config --global user.email "docker@example.com" +RUN git config --global user.name "Docker Container" + +CMD ["python", "download_and_compare.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..21b3191 --- /dev/null +++ b/README.md @@ -0,0 +1,103 @@ +# Language File Download and Compare Docker + +This Docker container downloads language JSON files from a specified URL, compares them with existing files, and automatically commits and pushes changes to a Git repository. + +## Features + +- Downloads language files for multiple languages +- Compares new files with existing ones +- Generates diff files for changes +- Automatically commits and pushes changes to Git +- Supports 15 languages: en, zh-TW, ja, ko, fr, de, es, it, nl, pl, pt, ru, tr, vi, zh-CN + +## Setup + +1. Copy `env.example` to `.env` and configure your Git repository: + ```bash + cp env.example .env + ``` + +2. Edit `.env` with your Git repository details and authentication method: + + **Method 1: Personal Access Token (Recommended)** + ``` + GIT_REPO_URL=https://github.com/yourusername/yourrepo.git + GIT_USERNAME=yourusername + GIT_EMAIL=your.email@example.com + GIT_BRANCH=main + GITHUB_TOKEN=ghp_your_personal_access_token_here + ``` + + **Method 2: SSH Key** + ``` + GIT_REPO_URL=git@github.com:yourusername/yourrepo.git + GIT_USERNAME=yourusername + GIT_EMAIL=your.email@example.com + GIT_BRANCH=main + ``` + +3. Build and run the container: + ```bash + docker-compose up --build + ``` + +## GitHub Authentication + +### Personal Access Token (Recommended) +1. Go to GitHub → Settings → Developer settings → Personal access tokens +2. Generate a new token with `repo` scope +3. Add the token to your `.env` file as `GITHUB_TOKEN` +4. Use HTTPS URLs: `https://github.com/username/repo.git` + +### SSH Key Authentication +1. Generate SSH key pair: `ssh-keygen -t ed25519 -C "your_email@example.com"` +2. Add public key to GitHub → Settings → SSH and GPG keys +3. Use SSH URLs: `git@github.com:username/repo.git` +4. Mount your private key in docker-compose (see Advanced Configuration) + +## Local Testing + +For local testing on your machine: + +1. Install dependencies: + ```bash + pip install -r requirements.txt + ``` + +2. Create a `.env` file with your Git configuration (same as above) + +3. Run the script locally: + ```bash + python download_and_compare.py + ``` + +The script will automatically load environment variables from the `.env` file using python-dotenv. + +## Usage + +The container will: +1. Download language files from the configured URL +2. Compare with existing files +3. Generate diff files for any changes +4. Commit and push changes to the Git repository + +## Files Generated + +- `{lang}.json` - Current language files +- `{lang}.diff` - Diff files showing changes (only when changes detected) + +## Environment Variables + +- `GIT_REPO_URL` - URL of the Git repository to push to +- `GIT_USERNAME` - Git username for commits +- `GIT_EMAIL` - Git email for commits +- `GIT_BRANCH` - Git branch to use (defaults to 'main') + +## Running Manually + +To run the script manually outside of Docker: +```bash +python download_and_compare.py +``` + +The script will automatically load your `.env` file for local testing. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..16a4508 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: '3.8' + +services: + download-compare: + build: . + environment: + - GIT_REPO_URL=${GIT_REPO_URL} + - GIT_USERNAME=${GIT_USERNAME} + - GIT_EMAIL=${GIT_EMAIL} + - GIT_BRANCH=${GIT_BRANCH:-main} + volumes: + - ./data:/app/data + - ./.git:/app/.git + working_dir: /app diff --git a/download_and_compare.py b/download_and_compare.py new file mode 100644 index 0000000..3a0712c --- /dev/null +++ b/download_and_compare.py @@ -0,0 +1,133 @@ +import requests +import json +import os +import subprocess +import sys +from datetime import datetime +from dotenv import load_dotenv + +load_dotenv() + +lang_list = ['en','zh-TW','ja', 'ko', 'fr', 'de', 'es', 'it', 'nl', 'pl', 'pt', 'ru', 'tr', 'vi', 'zh-CN'] + +def run_git_command(command): + try: + result = subprocess.run(command, shell=True, capture_output=True, text=True, cwd="/app") + if result.returncode != 0: + print(f"Git command failed: {command}") + print(f"Error: {result.stderr}") + return False + return True + except Exception as e: + print(f"Error running git command: {e}") + return False + +def setup_git_repo(): + git_repo_url = os.environ.get('GIT_REPO_URL') + git_username = os.environ.get('GIT_USERNAME') + git_email = os.environ.get('GIT_EMAIL') + git_branch = os.environ.get('GIT_BRANCH', 'main') + github_token = os.environ.get('GITHUB_TOKEN') + + if not all([git_repo_url, git_username, git_email]): + print("Git environment variables not set. Skipping Git operations.") + return False + + if not os.path.exists("/app/.git"): + print("Initializing Git repository...") + if not run_git_command("git init"): + return False + + if github_token and git_repo_url.startswith('https://'): + print("Using GitHub Personal Access Token for authentication...") + auth_url = git_repo_url.replace('https://', f'https://{git_username}:{github_token}@') + if not run_git_command(f"git remote add origin {auth_url}"): + return False + else: + if not run_git_command(f"git remote add origin {git_repo_url}"): + return False + + if not run_git_command(f"git checkout -b {git_branch}"): + return False + + run_git_command(f"git config user.name '{git_username}'") + run_git_command(f"git config user.email '{git_email}'") + + if github_token: + run_git_command("git config credential.helper store") + + return True + +def commit_and_push_changes(): + if not os.path.exists("/app/.git"): + return False + + try: + run_git_command("git add .") + run_git_command("git commit -m 'Update language files'") + run_git_command("git push origin HEAD") + print("Changes committed and pushed to Git repository") + return True + except Exception as e: + print(f"Error pushing to Git: {e}") + return False + +def download_and_compare_json(lang): + url = f"https://highschool.stg.g123-cpp.com/1/g123/i18n/{lang}/texts/source_schooltest_1.json" + + try: + response = requests.get(url) + response.raise_for_status() + new_data = response.json() + except requests.RequestException as e: + print(f"Error downloading JSON: {e}") + return + except json.JSONDecodeError as e: + print(f"Error parsing JSON: {e}") + return + + old_data = {} + if os.path.exists(f"{lang}.json"): + try: + with open(f"{lang}.json", "r", encoding="utf-8") as f: + old_data = json.load(f) + except (json.JSONDecodeError, FileNotFoundError): + print(f"Warning: Could not read existing {lang}.json, treating as empty") + + diff_lines = [] + diff_lines.append(f"--- {lang}.json") + diff_lines.append(f"+++ {lang}.json") + diff_lines.append("") + + all_keys = sorted(set(old_data.keys()) | set(new_data.keys())) + + for key in all_keys: + if key not in old_data: + diff_lines.append(f"+{key}: {json.dumps(new_data[key], ensure_ascii=False)}") + elif key not in new_data: + diff_lines.append(f"-{key}: {json.dumps(old_data[key], ensure_ascii=False)}") + elif old_data[key] != new_data[key]: + diff_lines.append(f"-{key}: {json.dumps(old_data[key], ensure_ascii=False)}") + diff_lines.append(f"+{key}: {json.dumps(new_data[key], ensure_ascii=False)}") + + with open(f"{lang}.json", "w", encoding="utf-8") as f: + json.dump(new_data, f, indent=2, ensure_ascii=False) + + if len(diff_lines) > 3: + with open(f"{lang}.diff", "w", encoding="utf-8") as f: + f.write("\n".join(diff_lines)) + print(f"Changes detected: {len(diff_lines) - 3} lines affected") + print(f"Diff saved to {lang}.diff") + else: + print("No changes detected") + + print(f"New data saved to {lang}.json ({len(new_data)} keys)") + +if __name__ == "__main__": + git_enabled = setup_git_repo() + + for lang in lang_list: + download_and_compare_json(lang) + + if git_enabled: + commit_and_push_changes() diff --git a/env.example b/env.example new file mode 100644 index 0000000..ddb0ec7 --- /dev/null +++ b/env.example @@ -0,0 +1,12 @@ +GIT_REPO_URL=https://github.com/yourusername/yourrepo.git +GIT_USERNAME=yourusername +GIT_EMAIL=your.email@example.com +GIT_BRANCH=main + +# GitHub Authentication (choose one method): +# Method 1: Personal Access Token (recommended for HTTPS) +GITHUB_TOKEN=ghp_your_personal_access_token_here + +# Method 2: SSH Key (for SSH URLs) +# GIT_REPO_URL=git@github.com:yourusername/yourrepo.git +# SSH_PRIVATE_KEY_PATH=/path/to/your/private/key diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2b1be2a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +requests>=2.31.0 +python-dotenv>=1.0.0