Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions .github/workflows/sync_translations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,64 @@ name: 🌐 Sync Translations
on:
workflow_dispatch:

# Ensure only one sync workflow runs at a time
# Cancel any in-progress runs when a new one is triggered
concurrency:
group: translation-sync
cancel-in-progress: true

# We use a machine account PAT from secrets so workflows are triggered
# the default token is not needed and should be fully restricted
permissions: {}

jobs:
sync_translations:
name: 'Sync Translations with Crowdin'
timeout-minutes: 20
timeout-minutes: 50
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

with:
token: ${{ secrets.MACHINE_ACCOUNT_PAT }}
ref: 'main'
fetch-depth: 0

- name: Enforce minimum 30-minute gap between syncs
run: |
echo "Checking last sync time to enforce 30-minute minimum gap..."

# Fetch the i18n_sync branch to check last sync time
git fetch origin i18n_sync:i18n_sync 2>/dev/null || true

# Get timestamp of last commit on i18n_sync (if it exists)
if git rev-parse --verify i18n_sync >/dev/null 2>&1; then
LAST_SYNC_TIME=$(git log -1 --format=%ct i18n_sync)
CURRENT_TIME=$(date +%s)
ELAPSED=$((CURRENT_TIME - LAST_SYNC_TIME))
REMAINING=$((1800 - ELAPSED))

# Defensive: ensure REMAINING is never negative
if [ $REMAINING -lt 0 ]; then
REMAINING=0
fi

if [ $REMAINING -gt 0 ]; then
MINUTES=$((REMAINING / 60))
SECONDS=$((REMAINING % 60))
echo "Last sync was $ELAPSED seconds ago."
echo "Waiting $MINUTES minutes and $SECONDS seconds to respect Crowdin rate limiting..."
echo "Sync will start at: $(date -u -d "+${REMAINING} seconds" '+%Y-%m-%d %H:%M:%S UTC')"
sleep $REMAINING
else
echo "Last sync was $ELAPSED seconds ago (≥30 min)."
echo "Proceeding immediately."
fi
else
echo "No previous sync found on i18n_sync branch."
echo "Proceeding immediately."
fi
shell: bash

- name: Credential Prep
run: |
echo "CROWDIN_APIv2_PAT=${{ secrets.CROWDIN_APIv2_PAT }}" >> $GITHUB_ENV
Expand All @@ -32,7 +74,7 @@ jobs:
git reset --hard origin/main
shell: bash

- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these were changed because actions/checkout@v6 and actions/setup-node@v6 don’t exist and would fail at runtime. I switched them to @v4, which is the latest stable and supported version

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these were changed because actions/checkout@v6 and actions/setup-node@v6 don’t exist and would fail at runtime.

? source

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these were changed because actions/checkout@v6 and actions/setup-node@v6 don’t exist and would fail at runtime.

? source

https://github.com/actions/checkout/releases
https://github.com/actions/setup-node/releases

There is no published v6 release for either action, so using @v6 would fail at runtime. I switched them to @v4, which is the latest supported version.

Copy link
Member

@david-allison david-allison Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with:
node-version: 20

Expand Down