Merge pull request 'feat: add i18n-sync action to fetch translations and create pull requests' (#34) from feature/i18n-sync into main
Reviewed-on: #34 Reviewed-by: Böhringer_Sebastian_-_J._Schmalz_GmbH <Sebastian.Boehringer@schmalz.de> Reviewed-by: Maier David - J. Schmalz GmbH <david.maier@noreply.schmalz-git.git.onstackit.cloud>
This commit is contained in:
commit
f13ae2e528
4 changed files with 179 additions and 0 deletions
|
|
@ -19,6 +19,7 @@ on:
|
|||
- cache
|
||||
- checkout
|
||||
- helm-deploy
|
||||
- i18n-sync
|
||||
- inject-content
|
||||
- maven-build
|
||||
- pnpm-build
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ Shared actions for Forgejo CI/CD pipelines.
|
|||
| [cache](cache) | Cache files between workflow runs |
|
||||
| [checkout](checkout) | Action for checking out a repository |
|
||||
| [helm-deploy](helm-deploy) | Deploy a service to Kubernetes via Helm over SSH |
|
||||
| [i18n-sync](i18n-sync) | Fetch translations from i18n.schmalz.com and open a pull request |
|
||||
| [inject-content](inject-content) | Inject content into a file by appending or overwriting |
|
||||
| [maven-build](maven-build) | Action for building and validating Maven projects |
|
||||
| [pnpm-build](pnpm-build) | Action for building and validating with PNPM |
|
||||
|
|
|
|||
46
i18n-sync/README.md
Normal file
46
i18n-sync/README.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# i18n-sync
|
||||
|
||||
Fetches the latest translations from i18n.schmalz.com, commits them to a `chore/i18n` branch, and opens a pull request against the destination branch.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `i18n-application` | Yes | — | Application key in i18n.schmalz.com (e.g. `calculator`) |
|
||||
| `locales-folder` | No | `locales` | Path to the locales directory relative to the repository root |
|
||||
| `format-folder` | No | `""` | Directory containing the `package.json` whose format script should be run after downloading translations. Leave empty to skip formatting. |
|
||||
| `format-script` | No | `format` | pnpm script name to run for formatting (e.g. `format`, `format:fix`) |
|
||||
| `jfrog-token` | No | `""` | JFrog npm auth token (required when `format-folder` is set) |
|
||||
| `forgejo-token` | Yes | — | Forgejo token with `contents:write` and `pull-requests:write` access |
|
||||
| `destination-branch` | No | `dev` | Target branch for the pull request |
|
||||
|
||||
## Usage
|
||||
|
||||
Minimal — no formatting:
|
||||
|
||||
```yaml
|
||||
- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/i18n-sync@i18n-sync-v1
|
||||
with:
|
||||
i18n-application: my-app
|
||||
forgejo-token: ${{ secrets.FORGEJO_I18N_UPDATE_TOKEN }}
|
||||
```
|
||||
|
||||
With formatting after download:
|
||||
|
||||
```yaml
|
||||
- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/i18n-sync@i18n-sync-v1
|
||||
with:
|
||||
i18n-application: my-app
|
||||
locales-folder: frontend/locales
|
||||
format-folder: frontend
|
||||
jfrog-token: ${{ secrets.JFROG_TOKEN }}
|
||||
forgejo-token: ${{ secrets.FORGEJO_I18N_UPDATE_TOKEN }}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The action fails fast if the `chore/i18n` branch already exists, indicating a previous update is still pending review.
|
||||
- If no translation changes are detected after downloading, the action exits cleanly without creating a branch or PR.
|
||||
- Deleted languages (files removed from i18n.schmalz.com) are also staged for removal via `git add --all`.
|
||||
- `jq` is installed automatically if not present on the runner.
|
||||
- The `forgejo-token` must belong to a user or bot with `contents:write` and `pull-requests:write` permissions on the repository.
|
||||
131
i18n-sync/action.yml
Normal file
131
i18n-sync/action.yml
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
name: i18n Sync
|
||||
description: >
|
||||
Fetches the latest translations from i18n.schmalz.com, commits them to a
|
||||
chore/i18n branch, and opens a pull request against the destination branch.
|
||||
|
||||
inputs:
|
||||
i18n-application:
|
||||
description: Application key in i18n.schmalz.com (e.g. "calculator")
|
||||
required: true
|
||||
locales-folder:
|
||||
description: Path to the locales directory relative to the repository root
|
||||
required: false
|
||||
default: locales
|
||||
format-folder:
|
||||
description: >
|
||||
Directory containing the package.json whose format script should be run
|
||||
after downloading translations. Leave empty to skip formatting.
|
||||
required: false
|
||||
default: ""
|
||||
format-script:
|
||||
description: pnpm script name to run for formatting (e.g. "format", "format:fix")
|
||||
required: false
|
||||
default: format
|
||||
jfrog-token:
|
||||
description: JFrog npm auth token (required when format-folder is set)
|
||||
required: false
|
||||
default: ""
|
||||
forgejo-token:
|
||||
description: Forgejo token with contents:write and pull-requests:write access
|
||||
required: true
|
||||
destination-branch:
|
||||
description: Target branch for the pull request
|
||||
required: false
|
||||
default: dev
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install jq if missing
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
command -v jq >/dev/null 2>&1 || sudo apt-get install -y --no-install-recommends jq
|
||||
|
||||
- name: Configure git
|
||||
shell: bash
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ inputs.forgejo-token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
ORIGIN_URL=$(git remote get-url origin)
|
||||
CLEAN_URL=$(echo "$ORIGIN_URL" | sed 's|https://[^@]*@|https://|')
|
||||
git remote set-url origin "$(echo "$CLEAN_URL" | sed "s|https://|https://github-actions[bot]:${FORGEJO_TOKEN}@|")"
|
||||
|
||||
- name: Check if i18n branch already exists
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if git ls-remote --exit-code --heads origin "refs/heads/chore/i18n" >/dev/null 2>&1; then
|
||||
echo "Branch chore/i18n already exists. A previous i18n update is still pending."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Download translations
|
||||
shell: bash
|
||||
env:
|
||||
I18N_APPLICATION: ${{ inputs.i18n-application }}
|
||||
LOCALES_FOLDER: ${{ inputs.locales-folder }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git checkout -b chore/i18n
|
||||
|
||||
echo "Fetching available languages for application: $I18N_APPLICATION"
|
||||
languages_json=$(curl --fail-with-body -sSL "https://i18n.schmalz.com/api/languages?projectKey=$I18N_APPLICATION")
|
||||
|
||||
echo "$languages_json" | jq -r '.[]' | while read -r lang; do
|
||||
echo "Downloading language: $lang"
|
||||
curl --fail-with-body -sSL -o "${LOCALES_FOLDER}/${lang}.json" \
|
||||
"https://i18n.schmalz.com/api/${I18N_APPLICATION}/${lang}.json"
|
||||
done
|
||||
|
||||
- name: Format translations
|
||||
if: ${{ inputs.format-folder != '' }}
|
||||
uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/pnpm-build@pnpm-build-v1
|
||||
with:
|
||||
working-directory: ${{ inputs.format-folder }}
|
||||
jfrog-token: ${{ inputs.jfrog-token }}
|
||||
run-scripts: ${{ inputs.format-script }}
|
||||
check-dedupe: "false"
|
||||
|
||||
- name: Commit and push translations
|
||||
id: commit
|
||||
shell: bash
|
||||
env:
|
||||
LOCALES_FOLDER: ${{ inputs.locales-folder }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git add --all "${LOCALES_FOLDER}/"
|
||||
|
||||
if git diff-index --cached --quiet HEAD; then
|
||||
echo "No translation changes detected. Nothing to do."
|
||||
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git commit -m "chore: update translations via i18n"
|
||||
git push origin chore/i18n
|
||||
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create pull request
|
||||
if: ${{ steps.commit.outputs.has_changes == 'true' }}
|
||||
shell: bash
|
||||
env:
|
||||
TOKEN: ${{ inputs.forgejo-token }}
|
||||
DESTINATION_BRANCH: ${{ inputs.destination-branch }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
curl --fail-with-body -s -X POST \
|
||||
-H "Authorization: token ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/pulls" \
|
||||
-d "$(jq -n \
|
||||
--arg title "chore: update translations via i18n" \
|
||||
--arg head "chore/i18n" \
|
||||
--arg base "$DESTINATION_BRANCH" \
|
||||
--arg body "Automated translation update from i18n.schmalz.com" \
|
||||
'{title: $title, head: $head, base: $base, body: $body, delete_branch_after_merge: true}'
|
||||
)"
|
||||
Loading…
Add table
Add a link
Reference in a new issue