diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index fb8a2c1bb..f49e6f848 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,10 +15,17 @@ jobs: env: NODE_OPTIONS: '--max_old_space_size=4096' steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Checkout code uses: actions/checkout@v4 with: - token: ${{ secrets.GH_ACTIONS_REPO_PAT }} + token: ${{ steps.generate-token.outputs.token }} - name: Use Node.js uses: actions/setup-node@v4 @@ -33,6 +40,6 @@ jobs: - name: Deploy run: | git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/${{github.repository}}.git - npm run deploy -- -u "github-actions-bot " + npm run deploy -- -u "livecodes-ci[bot] <186997172+livecodes-ci[bot]@users.noreply.github.com>" env: - GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_REPO_PAT }} + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} diff --git a/.github/workflows/i18n-update-notify.yml b/.github/workflows/i18n-update-notify.yml index 1c389464c..908d3e536 100644 --- a/.github/workflows/i18n-update-notify.yml +++ b/.github/workflows/i18n-update-notify.yml @@ -12,9 +12,17 @@ jobs: runs-on: ubuntu-latest if: github.event.pull_request.merged && github.event.sender.login != 'github-actions[bot]' && !startsWith(github.head_ref, 'i18n/') steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Create comment on PR uses: actions/github-script@v6 with: + github-token: ${{ steps.generate-token.outputs.token }} script: | const commentBody = `## i18n Actions Source PR has been merged into the default branch. diff --git a/.github/workflows/i18n-update-pull.yml b/.github/workflows/i18n-update-pull.yml index 9eb486ccb..d18da9732 100644 --- a/.github/workflows/i18n-update-pull.yml +++ b/.github/workflows/i18n-update-pull.yml @@ -22,8 +22,17 @@ jobs: branch: ${{ steps.fetch-pr.outputs.branch }} steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Check out repository uses: actions/checkout@v4 + with: + token: ${{ steps.generate-token.outputs.token }} - name: Fetch PR details id: fetch-pr @@ -46,11 +55,14 @@ jobs: echo "newBranch=$NEW_BRANCH" >> $GITHUB_OUTPUT echo "branch=$PR_BRANCH" >> $GITHUB_OUTPUT + git config --global user.name "livecodes-ci[bot]" + git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com" + if [[ ! $(git ls-remote --heads origin $NEW_BRANCH) ]]; then skip "Branch \`$NEW_BRANCH\` does not exist." fi env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} runner: name: Runner @@ -62,10 +74,18 @@ jobs: PR_BRANCH: ${{ needs.precheck.outputs.branch }} steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Check out repository uses: actions/checkout@v4 with: ref: ${{ needs.precheck.outputs.newBranch }} + token: ${{ steps.generate-token.outputs.token }} - name: Setup Node uses: actions/setup-node@v4 @@ -88,8 +108,8 @@ jobs: - name: Commit changes run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "livecodes-ci[bot]" + git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com" git add . # Only commit if there are changes @@ -104,6 +124,7 @@ jobs: - name: Create a new i18n PR, comment on source PR and reaction uses: actions/github-script@v7 with: + github-token: ${{ steps.generate-token.outputs.token }} script: | const repoURL = context.payload.repository.html_url; const branchURL = `${repoURL}/tree/${process.env.NEW_BRANCH}`; @@ -178,9 +199,17 @@ jobs: SKIP_REASON: ${{ needs.precheck.outputs.skipReason }} steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Create reaction on PR uses: actions/github-script@v7 with: + github-token: ${{ steps.generate-token.outputs.token }} script: | const runURL = `${context.payload.repository.html_url}/actions/runs/${process.env.GITHUB_RUN_ID}`; const commentBody = `## i18n Actions: \`.i18n-update-pull\` diff --git a/.github/workflows/i18n-update-push.yml b/.github/workflows/i18n-update-push.yml index e2dca3d08..e2dc67c3f 100644 --- a/.github/workflows/i18n-update-push.yml +++ b/.github/workflows/i18n-update-push.yml @@ -22,8 +22,17 @@ jobs: branch: ${{ steps.fetch-pr.outputs.branch }} steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Check out repository uses: actions/checkout@v4 + with: + token: ${{ steps.generate-token.outputs.token }} - name: Fetch PR details id: fetch-pr @@ -44,6 +53,9 @@ jobs: echo "newBranch=$NEW_BRANCH" >> $GITHUB_OUTPUT echo "branch=$PR_BRANCH" >> $GITHUB_OUTPUT + git config --global user.name "livecodes-ci[bot]" + git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com" + if [[ $(git ls-remote --heads origin $NEW_BRANCH) ]]; then SKIP_REASON="Branch \`$NEW_BRANCH\` already exists." echo "$SKIP_REASON Exiting..." @@ -51,7 +63,7 @@ jobs: echo "skipReason=$SKIP_REASON" >> $GITHUB_OUTPUT fi env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} runner: name: Runner @@ -63,8 +75,17 @@ jobs: PR_BRANCH: ${{ needs.precheck.outputs.branch }} steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Check out repository uses: actions/checkout@v4 + with: + token: ${{ steps.generate-token.outputs.token }} - name: Setup Node uses: actions/setup-node@v4 @@ -84,8 +105,8 @@ jobs: - name: Commit changes run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "livecodes-ci[bot]" + git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com" git add . # Only commit if there are changes @@ -103,6 +124,7 @@ jobs: - name: Create comment and reaction on PR uses: actions/github-script@v7 with: + github-token: ${{ steps.generate-token.outputs.token }} script: | const repoURL = context.payload.repository.html_url; const branchURL = `${repoURL}/tree/${process.env.NEW_BRANCH}`; @@ -140,9 +162,17 @@ jobs: SKIP_REASON: ${{ needs.precheck.outputs.skipReason }} steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Create comment and reaction on PR uses: actions/github-script@v7 with: + github-token: ${{ steps.generate-token.outputs.token }} script: | const runURL = `${context.payload.repository.html_url}/actions/runs/${process.env.GITHUB_RUN_ID}`; const commentBody = `## i18n Actions: \`.i18n-update-push\` diff --git a/.github/workflows/i18n-update-scheduled.yml b/.github/workflows/i18n-update-scheduled.yml index e9362bba0..5c411b2aa 100644 --- a/.github/workflows/i18n-update-scheduled.yml +++ b/.github/workflows/i18n-update-scheduled.yml @@ -25,13 +25,24 @@ jobs: runs-on: ubuntu-latest steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Check out repository uses: actions/checkout@v4 with: fetch-depth: 0 + token: ${{ steps.generate-token.outputs.token }} - name: Switch to i18n branch run: | + git config --global user.name "livecodes-ci[bot]" + git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com" + if [[ $(git ls-remote --heads origin $BRANCH) ]]; then git config pull.rebase false git fetch origin $BRANCH:$BRANCH @@ -51,26 +62,24 @@ jobs: - name: Install dependencies run: npm ci - - name: Linting and fixing - run: npm run fix + # - name: Linting and fixing + # run: npm run fix - - name: Commit changes - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git add . + # - name: Commit changes + # run: | + # git add . - # Only commit if there are changes - git diff-index --quiet HEAD || git commit -m "i18n: update source texts" + # # Only commit if there are changes + # git diff-index --quiet HEAD || git commit -m "i18n: update source texts" - # Save SHA of the latest commit to English locale - echo "LAST_COMMIT_SHA_PUSH=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales/en)" >> $GITHUB_ENV + # # Save SHA of the latest commit to English locale + # echo "LAST_COMMIT_SHA_PUSH=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales/en)" >> $GITHUB_ENV - - name: Push changes - run: git push origin $BRANCH + # - name: Push changes + # run: git push origin $BRANCH - - name: Push source texts to Lokalise - run: npm run i18n-update-push -- $LOKALISE_BRANCH + # - name: Push source texts to Lokalise + # run: npm run i18n-update-push -- $LOKALISE_BRANCH - name: Import from Lokalise run: | @@ -83,8 +92,6 @@ jobs: - name: Commit changes run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" git add . # Only commit if there are changes @@ -105,10 +112,13 @@ jobs: echo "SKIP=true" >> $GITHUB_ENV fi + echo "LAST_COMMIT_SHA_PUSH=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales/en)" >> $GITHUB_ENV + - name: Create a new i18n PR if not exists uses: actions/github-script@v7 if: steps.check-diff.outputs.SKIP != 'true' with: + github-token: ${{ steps.generate-token.outputs.token }} script: | const prInfo = await github.rest.pulls.list({ owner: context.repo.owner, diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index 81f856f23..5cc831d1c 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -7,10 +7,17 @@ jobs: runs-on: ubuntu-latest if: contains(github.ref, 'refs/heads/releases/') steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Checkout code uses: actions/checkout@v4 with: - token: ${{ secrets.GH_ACTIONS_REPO_PAT }} + token: ${{ steps.generate-token.outputs.token }} - name: Get version id: vars @@ -19,4 +26,4 @@ jobs: - name: Create pull request to develop run: gh pr create --title "Prepare release ${{steps.vars.outputs.version}}" --body "Prepare release ${{steps.vars.outputs.version}}" --base develop --head "${{github.ref_name}}" env: - GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_REPO_PAT }} + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cf38f9a65..ac8892ef9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,10 +16,17 @@ jobs: env: NODE_OPTIONS: '--max_old_space_size=4096' steps: + - name: Generate Github Token for CI Bot + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ secrets.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + - name: Checkout code uses: actions/checkout@v4 with: - token: ${{ secrets.GH_ACTIONS_REPO_PAT }} + token: ${{ steps.generate-token.outputs.token }} - name: Get version id: vars @@ -64,7 +71,7 @@ jobs: files: | livecodes-${{steps.vars.outputs.version}}.tar.gz livecodes-${{steps.vars.outputs.version}}.zip - token: ${{ secrets.GH_ACTIONS_REPO_PAT }} + token: ${{ steps.generate-token.outputs.token }} - name: Create permanent URL if: startsWith(github.head_ref, 'releases/v') @@ -88,10 +95,10 @@ jobs: if: startsWith(github.head_ref, 'releases/v') run: gh pr create --title "release ${{steps.vars.outputs.version}}" --body "https://${{steps.vars.outputs.version}}.livecodes.io" --base main --head develop env: - GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_REPO_PAT }} + GITHUB_token: ${{ steps.generate-token.outputs.token }} - name: Create pull request to main (SDK) if: startsWith(github.head_ref, 'releases/sdk-v') run: gh pr create --title "release ${{steps.vars.outputs.version}}" --body "https://www.npmjs.com/package/livecodes" --base main --head develop env: - GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_REPO_PAT }} + GITHUB_token: ${{ steps.generate-token.outputs.token }} diff --git a/docs/docs/contribution/i18n.md b/docs/docs/contribution/i18n.md index 3c3c541d7..f13e2ddcc 100644 --- a/docs/docs/contribution/i18n.md +++ b/docs/docs/contribution/i18n.md @@ -168,6 +168,8 @@ Several npm scripts are available to facilitate the i18n workflow: - [`i18n-exclude`](../../../scripts/i18n-exclude.js): **(Only used in other scripts and should not be run locally)** Excludes all other i18n locales except for English from type checking, as they might stay outdated and cause errors. - The `` argument is required to specify whether the script is to exclude files or revert the exclusion. Valid values are `pre` and `post`. - This script only works when environment variable `BUILD_INCLUDE_LOCALES` is **NOT** set to `true`. +- [`i18n-lokalise-json`](../../../scripts/i18n-lokalise-json.mjs): Generates `.lokalise.json` files from codebase for manually authoring translations on Lokalise. + - The `` argument is required to specify the language that the `.lokalise.json` files are generated from. Please run `i18n-export` before pushing changes to the codebase to ensure that the source texts are up-to-date. @@ -183,7 +185,11 @@ We consider the i18n process to consist of two parts: This means there are no changes to the source code/texts, only translations are updated. Adding new languages or updating existing translations are examples of this part. -In such cases, there is a scheduled workflow [`i18n-update-scheduled`](../../../.github\workflows\i18n-update-scheduled.yml) to handle this. The workflow will sync between the `master` branch on Lokalise and the `i18n/develop` branch on the codebase, then automatically create a PR if there are any changes. Basically, maintainers do not need to pay too much attention to this part except for reviewing the PRs. +In such cases, there is a scheduled workflow [`i18n-update-scheduled`](../../../.github/workflows/i18n-update-scheduled.yml) to handle this. The workflow will sync from the `master` branch on Lokalise to the `i18n/develop` branch on the codebase, then automatically create a PR if there are any changes. + +Basically, maintainers only need to focus on the following for this part: +- Reviewing PRs created by the `i18n-update-scheduled` workflow +- Do merging on Lokalise after they consider the translation for a specific feature is ready, before commenting `.i18n-update-pull` to trigger the `i18n-update-pull` workflow #### Source Update @@ -193,18 +199,18 @@ This means new changes are made to the source code/texts. In this case, maintain 2. Once a new feature or version is ready, developers run `npm run i18n-export` to extract and update all marked strings, then export them to `.lokalise.json` and `.ts` files. 3. Developers commit and push the changes to the repository. A feature PR is created and reviewed, and related tests, checks, and manual review could be carried out. 4. After the PR is merged, an auto-generated comment will notify maintainers to comment `.i18n-update-push` to trigger the `i18n-update-push` workflow when they think it is ready. -5. Maintainers comment `.i18n-update-push` to trigger the `i18n-update-push` workflow. The workflow will create a new branch named `i18n/`, run `npm run i18n-export` again to ensure the source texts are up-to-date, and push the changes. Then, it will push the changes to the `i18n/` branch on Lokalise. +5. Maintainers comment `.i18n-update-push` to trigger the `i18n-update-push` workflow. The workflow will create a new branch named `i18n//`, run `npm run i18n-export` again to ensure the source texts are up-to-date, and push the changes. Then, it will push the changes to the `i18n//` branch on Lokalise. 6. Translators can start translating the texts on Lokalise. -7. Once the translation is complete, maintainers can comment `.i18n-update-pull` to trigger the `i18n-update-pull` workflow. The workflow will pull the translated texts from Lokalise, update the `.ts` files under `src/livecodes/i18n/locales`, and commit the changes to the `i18n/` branch. Then, it will create a PR to merge the changes back to the default branch `develop`. -8. Maintainers should perform a final review on the i18n PR and merge it if everything is fine. +7. Once the translation is complete, maintainers can comment `.i18n-update-pull` to trigger the `i18n-update-pull` workflow. The workflow will pull the translated texts from Lokalise, update the `.ts` files under `src/livecodes/i18n/locales`, and commit the changes to the `i18n//` branch. Then, it will create a PR to merge the changes back to the default branch `develop`. +8. Maintainers should perform a final review on the i18n PR and merge it if everything is fine. Meanwhile, a merging from the `i18n//` to `master` should also be done to keep the `master` branch on Lokalise up-to-date. ### Github Actions (CI) Four i18n-related workflows are set up in the repository: - [`i18n-update-notify`](../../../.github\workflows\i18n-update-notify.yml): Creates a comment on merged PRs to notify maintainers to trigger the `i18n-update-push` workflow. -- [`i18n-update-push`](../../../.github\workflows\i18n-update-push.yml): Creates a new branch named `i18n/`, runs `npm run i18n-export` again to ensure the source texts are up-to-date, pushes the changes on git, then pushes the changes to the `i18n/` branch on Lokalise. -- [`i18n-update-pull`](../../../.github\workflows\i18n-update-pull.yml): Pulls the translated texts from Lokalise, updates the `.ts` files under `src/livecodes/i18n/locales`, commits the changes to the `i18n/` branch, then creates a PR to merge the changes back to the default branch `develop`. +- [`i18n-update-push`](../../../.github\workflows\i18n-update-push.yml): Creates a new branch named `i18n//`, runs `npm run i18n-export` again to ensure the source texts are up-to-date, pushes the changes on git, then pushes the changes to the `i18n//` branch on Lokalise. +- [`i18n-update-pull`](../../../.github\workflows\i18n-update-pull.yml): Pulls the translated texts from Lokalise, updates the `.ts` files under `src/livecodes/i18n/locales`, commits the changes to the `i18n//` branch, then creates a PR to merge the changes back to the default branch `develop`. - [`i18n-update-scheduled`](../../../.github\workflows\i18n-update-scheduled.yml): Syncs between the `master` branch on Lokalise and the `i18n/develop` branch on the codebase, then automatically creates a PR if there are any changes. ### Hashing and Cache @@ -225,8 +231,15 @@ File hashing is also applied to translation files during build, by auto-generati ## For Those Who Forked the Repo -To ensure the i18n workflow functions properly, `Workflow permissions` in `Settings > Actions > General` should be set to `Read and write permissions`, and make sure that `Allow GitHub Actions to create and approve pull requests` is enabled. +This repository is utilizing [LiveCodes CI](https://github.com/apps/livecodes-ci) Github App to ensure the i18n workflow functions properly. + +For forked repositories, maintainers should set up their own Lokalise project and Github App (see [here](https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#authenticating-with-github-app-generated-tokens)) to handle the i18n workflow. Changes to related workflow files are necessary. -`LOKALISE_API_TOKEN` should be set as a repository secret, while `LOKALISE_PROJECT_ID` should be set as a repository variable. +### Secrets and Variables Checklist +#### Repository Secrets +- `LOKALISE_API_TOKEN` +- `CI_APP_ID` +- `CI_APP_PRIVATE_KEY` -For private forks, `GITHUB_TOKEN` in workflow files should be set to a personal access token (PAT) with proper permissions. +#### Repository Variables +- `LOKALISE_PROJECT_ID`