From f8eccd6c43a1ddde25113c9936ce9aabde659fcd Mon Sep 17 00:00:00 2001 From: 3w36zj6 <52315048+3w36zj6@users.noreply.github.com> Date: Sun, 26 Oct 2025 08:50:00 +0900 Subject: [PATCH 1/2] chore: add workflow to merge upstream changes --- .gitattributes | 5 ++ .github/workflows/merge-upstream.yml | 120 +++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/workflows/merge-upstream.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..4120f01700 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# typst-jp/docs repository specific merge strategies +.github/workflows/* merge=ours +.github/ISSUE_TEMPLATE/* merge=ours +README.md merge=ours +CONTRIBUTING.md merge=ours diff --git a/.github/workflows/merge-upstream.yml b/.github/workflows/merge-upstream.yml new file mode 100644 index 0000000000..63ab2ddb5b --- /dev/null +++ b/.github/workflows/merge-upstream.yml @@ -0,0 +1,120 @@ +name: Merge upstream changes + +on: + workflow_dispatch: + inputs: + upstream_ref: + description: "Upstream tag to merge" + required: true + type: string + +permissions: + contents: write + pull-requests: write + +jobs: + merge-upstream: + runs-on: ubuntu-24.04 + steps: + - name: Checkout repository + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + + - name: Configure Git + run: | + git config --global user.name 'GitHub Actions' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + # Set up 'ours' merge driver + git config --global merge.ours.driver true + + - name: Create new branch + run: | + git checkout -b feature/merge-upstream-${{ github.event.inputs.upstream_ref }} + + - name: Add upstream remote + run: | + git remote add upstream https://github.com/typst/typst.git + git fetch upstream + + - name: Attempt merge with commit markers + run: | + # Try to merge but allow conflicts + TARGET_COMMIT=$(git rev-parse ${{ github.event.inputs.upstream_ref }}) + git merge --no-commit --no-ff --allow-unrelated-histories $TARGET_COMMIT || true + + # Remove upstream `.github/` directory + git checkout HEAD -- .github/ + git reset HEAD .github/ + + # Commit the merge with conflict markers + git commit -a -m "Merge upstream changes from ${{ github.event.inputs.upstream_ref }}" + + - name: Push branch + run: | + git push --force origin feature/merge-upstream-${{ github.event.inputs.upstream_ref }} + + - name: Create Pull Request + id: create-pr + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 + env: + PR_BODY: | + > [!CAUTION] + > コンフリクトの解消のため、このPull Requestは必ず**Create a merge commit**でマージしてください。 + + このPull Requestでは、[上流リポジトリ](https://github.com/typst/typst)の[`${{ github.event.inputs.upstream_ref }}`](https://github.com/typst/typst/releases/tag/${{ github.event.inputs.upstream_ref }})の変更をマージします。 + + with: + script: | + const pr = await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + head: "feature/merge-upstream-${{ github.event.inputs.upstream_ref }}", + base: "main", + title: "Merge upstream ${{ github.event.inputs.upstream_ref }}", + body: process.env.PR_BODY + }); + core.setOutput("pr_number", pr.data.number); + + - name: Check for conflict markers + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 + with: + script: | + const fs = require('fs'); + const path = require('path'); + + function findConflictMarkers(dirPath, conflictFiles = []) { + const files = fs.readdirSync(dirPath); + + for (const file of files) { + const filePath = path.join(dirPath, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + if (!['.git', 'node_modules', '.github'].includes(file)) { + findConflictMarkers(filePath, conflictFiles); + } + } else if (!['.lock', '.lockb'].some(ext => file.endsWith(ext))) { + try { + const content = fs.readFileSync(filePath, 'utf8'); + if (/^(<{7}|={7}|>{7})/m.test(content)) { + conflictFiles.push(filePath); + } + } catch (e) { + // Skip binary files + } + } + } + + return conflictFiles; + } + + const conflictFiles = findConflictMarkers('.'); + + if (conflictFiles.length > 0) { + const fileList = conflictFiles.map(f => `- \`${f}\``).join('\n'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: ${{ steps.create-pr.outputs.pr_number }}, + body: `> [!WARNING]\n> コンフリクトマーカーが検出されました。以下のファイルを確認し、コンフリクトを解消してください。\n\n${fileList}` + }); + } From ff6934048992467d86683a29eba0f03066243aa1 Mon Sep 17 00:00:00 2001 From: 3w36zj6 <52315048+3w36zj6@users.noreply.github.com> Date: Sun, 26 Oct 2025 10:15:47 +0900 Subject: [PATCH 2/2] refactor: simplify conflict marker detection using git grep --- .github/workflows/merge-upstream.yml | 60 ++++++++++------------------ 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/.github/workflows/merge-upstream.yml b/.github/workflows/merge-upstream.yml index 63ab2ddb5b..e07c4f0a27 100644 --- a/.github/workflows/merge-upstream.yml +++ b/.github/workflows/merge-upstream.yml @@ -75,46 +75,26 @@ jobs: core.setOutput("pr_number", pr.data.number); - name: Check for conflict markers + id: check-conflicts + run: | + CONFLICT_FILES=$(git grep -l "^<<<<<<<\|^=======\|^>>>>>>>" HEAD || echo "") + if [ -n "$CONFLICT_FILES" ]; then + echo "has_conflicts=true" >> $GITHUB_OUTPUT + echo "conflict_files<> $GITHUB_OUTPUT + echo "$CONFLICT_FILES" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Comment on Pull Request if conflicts found + if: steps.check-conflicts.outputs.has_conflicts == 'true' uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | - const fs = require('fs'); - const path = require('path'); - - function findConflictMarkers(dirPath, conflictFiles = []) { - const files = fs.readdirSync(dirPath); - - for (const file of files) { - const filePath = path.join(dirPath, file); - const stat = fs.statSync(filePath); - - if (stat.isDirectory()) { - if (!['.git', 'node_modules', '.github'].includes(file)) { - findConflictMarkers(filePath, conflictFiles); - } - } else if (!['.lock', '.lockb'].some(ext => file.endsWith(ext))) { - try { - const content = fs.readFileSync(filePath, 'utf8'); - if (/^(<{7}|={7}|>{7})/m.test(content)) { - conflictFiles.push(filePath); - } - } catch (e) { - // Skip binary files - } - } - } - - return conflictFiles; - } - - const conflictFiles = findConflictMarkers('.'); - - if (conflictFiles.length > 0) { - const fileList = conflictFiles.map(f => `- \`${f}\``).join('\n'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: ${{ steps.create-pr.outputs.pr_number }}, - body: `> [!WARNING]\n> コンフリクトマーカーが検出されました。以下のファイルを確認し、コンフリクトを解消してください。\n\n${fileList}` - }); - } + const files = `${{ steps.check-conflicts.outputs.conflict_files }}`.split('\n').filter(f => f); + const fileList = files.map(f => `- \`${f}\``).join('\n'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: ${{ steps.create-pr.outputs.pr_number }}, + body: `> [!WARNING]\n> コンフリクトマーカーが検出されました。以下のファイルを確認し、コンフリクトを解消してください。\n\n${fileList}` + });