Commit Graph

58 Commits

Author SHA1 Message Date
Gu
0de36b955a add trigger restrictions 2025-11-17 18:13:58 +08:00
Gu
d87ba0a4fc fix: prevent duplicate commits in execute workflow
Problem:
Both execute and update workflows were triggering for the same commit
when a translation PR already existed, causing duplicate auto-sync
commits (e.g., commit 2ddf04bc in PR #167 created two identical commits
in PR #168).

Root Cause:
- Execute workflow (sync_docs_execute.yml) - handles initial PR creation
- Update workflow (sync_docs_update.yml) - handles incremental updates
- Both listen for "Analyze Documentation Changes" workflow completion
- No coordination to prevent both from running when translation PR exists

Solution:
Execute workflow now skips all translation steps if translation branch
already exists, letting the update workflow handle incremental changes.
This ensures only one workflow processes each commit.

Changes:
- Added "Skip if translation PR already exists" step after branch check
- Updated all subsequent steps to check branch_exists != 'true'
- Steps affected: Python setup, dependencies, approval check, translation,
  and PR comments

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-12 05:00:15 +08:00
Gu
87e81b8185 clear hard coded language codes 2025-11-06 17:35:13 -08:00
Gu
90f9c9381c clean up 2025-11-06 16:16:08 -08:00
Gu
69ec60fdcd feat: auto-close sync PRs when original PR closes
Add cleanup workflow that:
- Triggers when a PR is closed (merged or not)
- Finds the corresponding sync PR (docs-sync-pr-{N})
- Closes it with appropriate message:
  - If merged: "You can still merge sync PR independently"
  - If closed: "Sync will resume if PR reopens"

Prevents orphaned sync PRs cluttering the PR list.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 14:33:33 -08:00
Gu
07580bfd52 refactor: simplify naming and reduce comment verbosity
Changes:
- PR title: "Auto-translations" → "Sync PR #X to cn/jp"
- PR body: More concise, clearer
- Workflow comments: Drastically simplified
  - "Translation PR" → "Sync PR"
  - Removed verbose sections, kept essential info only
  - Success: Link + file count + failures (if any)
  - Cancellation: Brief explanation + manual re-run link
  - Back-link: One sentence

Before: 20+ line comments with multiple sections
After: 2-5 line comments with just the facts

This makes the multi-language sync feature more straightforward for
doc writers without overwhelming them with information.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 14:24:49 -08:00
Gu
9e045e9b94 fix: escape multiline strings in cancellation handlers
Fix YAML parsing error caused by multiline template literals in
JavaScript code. Changed from backtick template literals to string
concatenation to avoid YAML parser confusion with markdown syntax.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 14:08:52 -08:00
Gu
d88a508389 feat: add cancellation notifications for skipped commits
Add handle-cancellation jobs to both Execute and Update workflows to notify
doc writers when their commits are skipped due to rapid updates.

Features:
- Detects when workflows are cancelled due to concurrency
- Extracts PR number from analyze workflow artifacts
- Posts clear notification to PR explaining what happened
- Provides easy manual re-run instructions with direct link
- Recommends "do nothing" as default (latest commit always translated)

This makes the concurrency behavior transparent to doc writers and
gives them an easy path to re-run if needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 13:59:53 -08:00
Gu
15b424accf fix: use head_branch for concurrency groups
Use github.event.workflow_run.head_branch instead of pull_requests array
for concurrency grouping. The pull_requests array is empty in workflow_run
triggered workflows, causing all workflows to use the same empty group.

This ensures:
- Different PRs don't block each other
- Same PR's workflows serialize correctly
- Concurrency control actually works

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 13:34:20 -08:00
Gu
b5c7b1a854 fix: add concurrency control to translation workflows
- Add concurrency groups to both Execute and Update workflows
- Prevent race conditions when user pushes multiple commits quickly
- Queue workflows per PR instead of running concurrently
- Remove obsolete should_skip logic made redundant by concurrency groups

This ensures only one translation workflow runs per PR at a time,
eliminating git conflicts on the translation branch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 13:22:56 -08:00
Gu
dfe3bae4da fix: use workflow run ID for artifact naming
Changes:
- Use github.run_id in analyze workflow artifact name
- Use github.event.workflow_run.id in update workflow download
- This fixes the issue where PR number is not accessible in workflow_run context

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 13:02:16 -08:00
Gu
afbe2c1083 security: chain update workflow to analyze workflow with artifact validation
Critical security fix: Update workflow now properly waits for Analyze workflow completion and uses validated artifacts.

BEFORE (Security Gap):
- sync_docs_analyze.yml: read-only permissions, validates inputs
- sync_docs_update.yml: write permissions, re-runs analysis BYPASSING validations
- Both run in parallel independently
- Security checks (file size, count, path validation) were bypassed

AFTER (Secure Chain):
- sync_docs_analyze.yml: validates inputs with security checks
  - File count limit (max 50)
  - File size limit (10MB)
  - Path validation (no ../ traversal)
  - File type validation (.md, .mdx, .json only)
  - Creates validated sync_plan.json artifact
- sync_docs_update.yml: triggered ONLY after analyze succeeds
  - Downloads validated sync_plan.json artifact
  - Uses pre-validated inputs (no re-analysis)
  - Proceeds with write operations only if validation passed

Changes:
- Trigger: pull_request → workflow_run on analyze completion
- Removed: check-event-type job (redundant)
- Removed: pr_analyzer validation (already done in analyze)
- Added: Artifact download from analyze workflow
- Added: Load and validate sync_plan.json
- Simplified: Single job that trusts validated inputs

Result: Proper security boundary where validation (read-only) and execution (write) are separated.
2025-11-06 12:48:55 -08:00
Gu
349676673b fix: extract Last-Processed-Commit from git log instead of PR comments
The update workflow was looking for Last-Processed-Commit in PR comments,
but translate_pr.py puts it in commit messages. This caused the workflow
to fall back to PR base, comparing from main branch instead of the last
processed commit, resulting in all PR files being re-translated.

Changed to use 'git log' to extract Last-Processed-Commit from the most
recent commit message in the translation branch.
2025-11-06 07:56:02 -08:00
Gu
0c5325c7fc fix: add is_incremental to analysis.json for execute workflow compatibility
The execute workflow expects is_incremental field in analysis.json, but
the refactored analyze workflow wasn't including it. Added IS_INCREMENTAL
variable extraction and include it in the metadata.
2025-11-06 07:45:37 -08:00
Gu
725749fc5c feat: abstract sync_plan generation logic into SyncPlanGenerator
Consolidates sync_plan.json generation logic from analyze workflow into
reusable SyncPlanGenerator class to ensure both execute and update workflows
use identical file filtering and docs.json change detection.

**Problems Solved:**

1. **Unnecessary Re-translations**: Update workflow was re-translating
   unchanged files because it hardcoded structure_changed: true and got
   ALL files from PR instead of only A/M files.

2. **docs.json Not Syncing**: Update workflow lacked proper docs.json
   change analysis, causing navigation structure to not update correctly.

**Changes:**

- **pr_analyzer.py**: Added SyncPlanGenerator class with:
  - get_changed_files_with_status(): Uses git diff --diff-filter=AM
  - generate_sync_plan(): Identical logic to analyze workflow
  - Proper docs.json change detection (not always true)

- **translate_pr.py**: Updated run_translation_from_pr_analysis() to:
  - Use SyncPlanGenerator instead of hardcoded sync_plan
  - Remove structure_changed: true assumption
  - Add detailed logging of sync plan contents

- **sync_docs_analyze.yml**: Simplified from 70 lines to 40 lines:
  - Replaced inline Python script with SyncPlanGenerator call
  - Maintains all functionality with cleaner code
  - Single source of truth for sync logic

**Benefits:**

 Only A/M files are translated (no re-translation of unchanged files)
 docs.json changes are properly analyzed (not assumed)
 Both workflows use identical sync logic
 ~30 lines of duplicate code eliminated
 Easier to test and maintain
 Consistent behavior across execute and update workflows
2025-11-06 07:43:07 -08:00
Gu
25fc4fcff0 fix: prevent race condition properly while maintaining security
Instead of removing 'synchronize' trigger from analyze workflow (which is
needed for security checks), we now make the execute workflow skip when:
- It's an incremental update (synchronize event)
- AND a translation branch already exists

This ensures:
- Security checks always run (analyze workflow on all PR events)
- No race condition (execute skips, update handles incremental changes)
- Initial PRs still work (execute runs when no translation branch exists)

The logic:
- PR opened/reopened: analyze → execute → create new translation PR
- PR synchronized: analyze (security) + update → update existing translation PR
  - Execute workflow sees incremental=true + branch_exists=true and skips
2025-11-06 07:10:31 -08:00
Gu
6f29c102b4 fix: prevent race condition between analyze and update workflows
Remove 'synchronize' from analyze workflow triggers to prevent both
analyze→execute and update workflows from running simultaneously when
a PR is updated.

Now:
- opened/reopened → analyze → execute (create new translation PR)
- synchronize → update (update existing translation PR incrementally)
2025-11-06 07:00:31 -08:00
Chenhe Gu
656b08c211 Refactor: Extract translation logic into reusable Python script (#94)
* refactor: extract translation logic into reusable Python script

- Created tools/translate/translate_pr.py to consolidate translation workflow
- Refactored sync_docs_execute.yml: reduced from 941 to 513 lines
- Refactored sync_docs_update.yml: reduced from 552 to 381 lines
- Total reduction: ~600 lines of duplicated workflow YAML

Benefits:
- Single source of truth for translation logic
- All fixes (English file removal, branch handling) automatically apply to both workflows
- Easier to test and maintain
- Reusable Python module with proper error handling

The script handles:
- Branch setup (create new or checkout existing)
- Translation of documentation files
- English file removal (fixes the leak bug)
- Committing and pushing changes
- Creating/updating translation PRs
- JSON output for workflow integration

* touch ups

* more touch ups
2025-11-06 06:33:23 -08:00
Gu
4364b9b414 fix: remove English files after translation before commit
The issue was that line 320 checks out English files from the PR
(git checkout $HEAD_SHA -- en/) for translation purposes, but these
files remained in the working directory when committing.

The previous fix (find command at line 691) wasn't effective because:
1. It only removed files matching ./en/* pattern
2. Files might have already been staged by git

This fix:
1. Uses rm -rf to explicitly remove en/*.md and en/*.mdx files
2. Explicitly unstages any en/ files with git reset
3. Runs right before git add to ensure clean commits
2025-11-06 04:05:17 -08:00
Gu
485b51b1e9 fix: check branch existence after repo checkout
The branch existence check was running before the repo was checked out,
causing git ls-remote to fail or return incorrect results. This led to
the workflow creating new branches instead of checking out existing ones,
resulting in:
1. English source files leaking into translation branches
2. Non-fast-forward push errors on incremental updates

Moving the check after PR branch checkout ensures we have full repo
access when checking if the translation branch exists.
2025-11-06 03:59:24 -08:00
Chenhe Gu
a13ecaa804 Revert "Test: Fresh Incremental Translation - Round 2" (#87) 2025-11-06 03:29:30 -08:00
Gu
4d5cb2edbe Merge branch 'test/incremental-fresh-2' - fix branch existence check 2025-11-06 03:23:47 -08:00
Gu
84703cace2 fix: use GitHub API to check branch existence 2025-11-06 03:23:20 -08:00
Gu
a287744248 fix: use git checkout -B to handle local branch conflicts 2025-11-06 02:34:24 -08:00
Gu
83459027e3 fix: remove English source files from translation branch
After checkout translation branch, remove English source files that remain
in working directory from PR branch checkout. This prevents English files
from being accidentally committed to translation PR.

Also addresses issue where first Japanese file was being modified during
incremental updates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 22:42:21 -08:00
Gu
75e7944a6a fix: checkout existing translation branch before committing
When translation branch exists remotely, fetch and checkout it before
making incremental commits. This prevents non-fast-forward errors.

Fixes the issue where second commit would fail to push because it was
trying to push from PR branch to translation branch without checking
out the translation branch first.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 11:33:51 -08:00
Gu
d4be02b3c3 fix: resolve YAML syntax errors in workflow files
Replace heredoc syntax with bash variable assignments using $'\n' for newlines.
Fix indentation of JavaScript template literals in script blocks.

Root cause: Multi-line strings in bash and JavaScript template literals
must be properly indented within YAML literal block scalars to prevent
parser errors.

\ud83e\udd16 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 11:19:17 -08:00
Gu
cb56daab8b chore: force workflow re-parse by GitHub Actions
Add comments to trigger GitHub to re-scan and update workflow metadata.
This should fix the issue where workflow names show as file paths instead
of the defined name field.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 11:09:39 -08:00
Chenhe Gu
e92b73d446 fix: YAML syntax error in multi-line commit messages (#79)
Use heredoc with command substitution for multi-line git commit messages
in bash scripts within YAML workflows to prevent parsing errors.

Fixes:
- sync_docs_execute.yml: Both incremental and initial commit messages
- sync_docs_update.yml: Update commit messages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-06 00:32:12 +09:00
Chenhe Gu
6d78478c45 feat: implement commit-based incremental translation workflow (#77)
Implements full incremental translation system with commit-based change detection:

## Key Features

### 1. Incremental Change Detection (analyze workflow)
- Detects synchronize events and compares with last processed commit
- Queries translation PR for Last-Processed-Commit from comments
- Falls back to github.event.before, then PR base
- Passes is_incremental flag to sync plan

### 2. Append-Only Translation Commits (execute workflow)
- Checks if translation branch exists before creating/updating
- For existing branches: fetches and appends new commit
- For new branches: creates initial translation commit
- Embeds Last-Processed-Commit: SHA in commit message
- Removes --force push to preserve history
- Adds tracking comment to translation PR

### 3. Incremental Update System (update workflow)
- Queries translation PR for last processed commit
- Uses incremental comparison range for re-translation
- Appends update commits with tracking metadata
- No force-push - preserves full commit history

## Benefits

- **Efficiency**: Only translates changed files (~10x API reduction)
- **Traceability**: 1:1 mapping between source and translation commits
- **Robustness**: Handles force-pushes gracefully via persistent tracking
- **History**: Preserved translation timeline, not overwritten

## Breaking Changes

None - workflows are backward compatible with existing PRs.
2025-11-06 00:20:10 +09:00
Gu
080c828034 fix 2025-11-01 17:25:06 -07:00
Gu
680279ee7d fix 2025-11-01 04:31:17 -07:00
Gu
ba4c150e34 add handling for openapi json files 2025-11-01 03:35:24 -07:00
Gu
42dcdd43b1 . 2025-11-01 01:37:05 -07:00
Gu
ad6a4a61c7 refactor: unify language config into single source of truth
## Changes

### Unified Configuration
- Centralized all language configuration in `tools/translate/config.json`
- Added `source_language`, `target_languages`, and `languages` structure
- Merged translation notices from `notices.json` into language configs
- Each language now has: code, name, directory, and translation_notice

### Updated sync_and_translate.py
- Removed hardcoded LANGUAGES dict and TARGET_LANGUAGES list
- Enhanced load_config() with validation
- Added helper methods for language info access
- All methods now use config-based language properties

### Updated main.py
- Added config loading at module level
- Dynamically builds docs_structure from config
- Keeps plugin-dev/versioned paths hardcoded as requested

### Updated workflow
- .github/workflows/sync_docs_execute.yml now loads config
- Replaced all hardcoded language references with config values

### Cleanup
- Removed deprecated notices.json

### Test File
- Added en/testing/config-refactor-test.mdx to test the refactoring
- Added to docs.json to trigger auto-translation workflow

## Benefits
- Single source of truth for language configuration
- Adding new languages requires only config.json changes
- No code changes needed to add/modify languages
- Better validation and error handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 10:36:51 -07:00
Gu
dcb2e4329f feat: enhance translation workflow for modified docs
Improved auto-translation system to better handle updates to existing documentation:

**Core Changes:**
- Updated translate_text() to accept optional `the_doc_exist` and `diff_original` parameters
- Added get_file_diff() helper method to retrieve git diffs for specific files
- Enhanced translate_file_with_notice() to pass optional parameters to translation API

**Modified File Handling:**
- Refactored translate_new_and_modified_files() to distinguish between added and modified files
- For modified files: loads existing translation and retrieves git diff
- For added files: continues with existing flow (no additional inputs needed)
- Passes both existing translation and diff to Dify API for context-aware updates

**Workflow Updates:**
- Updated sync_docs_execute.yml inline secure_sync.py script
- Detects file status (added vs modified) using git diff
- Loads existing translations for modified files
- Retrieves diffs for modified files
- Passes appropriate inputs based on file status

**Benefits:**
- New translations for modified files generated based on existing translation and diff
- Maintains translation consistency across updates
- Reduces re-translation of unchanged content
- Improves translation quality for incremental changes

🤖 Generated with Claude Code
2025-10-30 09:31:05 -07:00
Gu
ed22f82bee remove old config file 2025-10-30 08:07:16 -07:00
Gu
19eaf49ebc avoid failure notification 2025-10-30 07:50:58 -07:00
Gu
138ce90fde add filler job 2025-10-30 06:06:23 -07:00
Gu
1019bef876 fix: improve deletion handling and add comprehensive logging
Improvements:
- Add detailed logging for git diff detection of deleted files
- Add comprehensive logging in sync_docs_json_incremental for deletions
- Track each step of the deletion process to aid debugging
- Add error handling and traceback output for failed operations
- Log dropdown search process and removal attempts

This will help diagnose why cn/jp entries are not being removed from
docs.json when English files are deleted. The test in test_delete_logic.py
proves the remove_page_from_structure method works correctly, so the issue
must be in how deleted_files are detected or how the workflow calls the sync.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 04:39:12 -07:00
Gu
9e9d3cc7a9 fix: delete translation files when English files are deleted
Previously, the workflows only removed entries from docs.json but did not
delete the actual cn/ and jp/ translation files when English files were deleted.

Changes:
- Add file deletion logic in sync_docs_execute.yml
- Add file deletion logic in sync_docs_update.yml
- Delete corresponding cn/ and jp/ files when en/ files are deleted
- Clean up empty parent directories after file deletion
- Track deleted files in workflow results

This ensures that when English documentation is deleted, the corresponding
translations are also removed from the repository, keeping the codebase clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 04:29:20 -07:00
Gu
0d935bfb9a fix docs.json sync scope and group name syncs 2025-10-30 01:18:06 -07:00
Gu
9639e9727c remove bundle workflow 2025-10-28 20:25:00 -07:00
crazywoola
0a84fee868 update: checks (#408) 2025-08-15 11:17:38 +08:00
crazywoola
d93ed7e7f9 chore: update template 2025-07-16 16:29:38 +08:00
crazywoola
ac34561dc2 chore: update tmpl 2025-07-16 16:27:53 +08:00
crazywoola
051938b0d3 feat: add template 2025-07-16 16:25:56 +08:00
Alter-xyz
98b84e3b7f !feat: action on pull request
main branch is now protected
2025-05-19 21:54:16 +08:00
Alter-xyz
2a089a31ff Update docs_bundle.yml 2025-05-19 17:31:11 +08:00
Alter-xyz
c75078ddd5 chore: action 2025-05-19 17:28:43 +08:00