diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml new file mode 100644 index 0000000..84cee86 --- /dev/null +++ b/.github/workflows/sync-upstream.yml @@ -0,0 +1,81 @@ +name: Sync Upstream and Release + +on: + schedule: + # Check for upstream changes daily at 00:00 UTC + - cron: '0 0 * * *' + workflow_dispatch: + inputs: + force_release: + description: 'Force a release even if no upstream changes' + required: false + default: 'false' + type: choice + options: + - 'false' + - 'true' + +env: + UPSTREAM_REPO: https://github.com/router-for-me/EasyCLI.git + UPSTREAM_BRANCH: main + +jobs: + sync: + name: Sync Upstream + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Add upstream remote + run: | + git remote add upstream ${{ env.UPSTREAM_REPO }} || true + git fetch upstream ${{ env.UPSTREAM_BRANCH }} + + - name: Check for upstream changes + id: check + run: | + LOCAL_SHA=$(git rev-parse HEAD) + UPSTREAM_SHA=$(git rev-parse upstream/${{ env.UPSTREAM_BRANCH }}) + + if [ "$LOCAL_SHA" = "$UPSTREAM_SHA" ] && [ "${{ github.event.inputs.force_release }}" != "true" ]; then + echo "No upstream changes detected." + echo "has_changes=false" >> "$GITHUB_OUTPUT" + else + echo "Upstream changes detected or force release requested." + echo "has_changes=true" >> "$GITHUB_OUTPUT" + fi + + - name: Merge upstream changes + if: steps.check.outputs.has_changes == 'true' + run: | + git merge upstream/${{ env.UPSTREAM_BRANCH }} --no-edit --allow-unrelated-histories || { + echo "::warning::Merge conflict detected. Resolving by keeping our changes." + git checkout --ours . + git add . + git commit -m "Merge upstream (conflicts resolved by keeping local)" + } + + - name: Push merged changes + if: steps.check.outputs.has_changes == 'true' + run: | + git push origin HEAD + + - name: Create release tag (triggers build workflow) + if: steps.check.outputs.has_changes == 'true' + run: | + DATE=$(date +%Y%m%d) + SHORT_SHA=$(git rev-parse --short HEAD) + TAG="v${DATE}-sync-${SHORT_SHA}" + echo "Creating tag: ${TAG}" + git tag "$TAG" + git push origin "$TAG" + echo "Tag pushed — the 'Release on Tag' workflow will handle the build." diff --git a/.gitignore b/.gitignore index b3a3f4c..71995d0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,15 @@ dist-web/ src-tauri/logs/ .serena/ AGENTS.md -CLAUDE.md \ No newline at end of file +CLAUDE.md + +# codex: local build artifacts +.vs/ +**/.vs/ +[Bb]in/ +[Oo]bj/ +**/[Bb]in/ +**/[Oo]bj/ +node_modules/ +**/node_modules/ +# codex: end local build artifacts \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7b9e15e..31579f0 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -914,6 +914,15 @@ fn generate_random_password() -> String { .collect() } +fn get_or_generate_secret_key(conf: &serde_yaml::Value) -> String { + conf.get("remote-management") + .and_then(|v| v.get("secret-key")) + .and_then(|v| v.as_str()) + .filter(|s| !s.trim().is_empty()) + .map(|s| s.to_string()) + .unwrap_or_else(generate_random_password) +} + fn start_monitor(app: tauri::AppHandle) { let proc_ref = Arc::clone(&PROCESS); thread::spawn(move || { @@ -1128,8 +1137,7 @@ fn start_cliproxyapi(app: tauri::AppHandle) -> Result eprintln!("[PORT_CLEANUP] Warning: {}", e); } - // Generate random password for local mode - let password = generate_random_password(); + let password = get_or_generate_secret_key(&conf); // Store the password for keep-alive authentication *CLI_PROXY_PASSWORD.lock() = Some(password.clone()); @@ -1258,8 +1266,7 @@ fn restart_cliproxyapi(app: tauri::AppHandle) -> Result<(), String> { eprintln!("[PORT_CLEANUP] Warning: {}", e); } - // Generate random password for local mode - let password = generate_random_password(); + let password = get_or_generate_secret_key(&conf); // Store the password for keep-alive authentication *CLI_PROXY_PASSWORD.lock() = Some(password.clone());