Files
actual/.github/workflows/i18n-string-extract-master.yml
Matiss Janis Aboltins d76d7d3204 Security hardening: validate release notes and workflow inputs (#7448)
* [AI] Harden GitHub Actions workflows against low-severity security issues

- generate-release-pr.yml: replace `eval` with an associative array for
  per-package version tracking. The version input was already moved to an
  env var in #7433, so this removes the remaining defense-in-depth concern
  of `eval`ing subshell output.
- create-release-notes-file.js: validate the OpenAI-returned category
  against the known allow-list (Features, Bugfixes, Enhancements,
  Maintenance), validate the author against the GitHub username regex,
  and collapse the summary to a single line before embedding it in the
  markdown body. Prevents indirect prompt-injection via CodeRabbit
  comments from producing malformed YAML frontmatter.
- generate-summary.js: stop logging the full CodeRabbit comment body to
  CI logs.
- netlify-release.yml, i18n-string-extract-master.yml: pass secrets via
  `env:` blocks rather than as CLI arguments, so they do not appear in
  argv / process listings.

https://claude.ai/code/session_012pZSkUBbabmmuaxbwysW33

* Add release notes for PR #7448

* [AI] Address review feedback on security hardening

- create-release-notes-file.js: stop logging the full fileContent body.
  Only log the target filename plus the (already-validated) category and
  author metadata, so the model-generated release-note text doesn't end
  up in CI logs.
- create-release-notes-file.js: validate summaryData.prNumber as a
  positive integer before using it in the file path or commit message,
  and switch both usages to the validated numeric value.
- i18n-string-extract-master.yml: write the Weblate API key into
  ~/.config/weblate under a [keys] section in a new "Configure Weblate
  API credentials" step, then drop the per-step env blocks and the
  --key CLI flag from every wlc invocation so the secret is no longer
  visible in process listings at all.

https://claude.ai/code/session_012pZSkUBbabmmuaxbwysW33

* [AI] Remove debug console.log statements for category in release notes script

Remove the four "Debug - ..." console.log calls that printed the raw
category env var (value/type/JSON-stringified form) plus the cleanCategory
value. They were clutter in CI logs; the existing info-level
"Creating release notes file: ... (category: ..., author: ...)" log
already surfaces the sanitized category.

https://claude.ai/code/session_012pZSkUBbabmmuaxbwysW33

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-10 17:11:52 +00:00

96 lines
3.1 KiB
YAML

name: Extract and upload i18n strings
on:
schedule:
# 4am UTC
- cron: '0 4 * * *'
workflow_dispatch:
jobs:
extract-and-upload-i18n-strings:
runs-on: ubuntu-latest
if: github.repository == 'actualbudget/actual'
steps:
- name: Check out main repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
path: actual
- name: Set up environment
uses: ./actual/.github/actions/setup
with:
working-directory: actual
download-translations: false # As we'll manually clone instead
- name: Configure Git config
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Configure i18n client
run: |
pip install wlc
- name: Configure Weblate API credentials
env:
WEBLATE_API_KEY: ${{ secrets.WEBLATE_API_KEY_CI_STRINGS }}
run: |
# Write the API key to wlc's config file instead of passing it on
# the command line, so the secret doesn't appear in process listings.
mkdir -p "$HOME/.config"
umask 077
cat > "$HOME/.config/weblate" <<EOF
[keys]
https://hosted.weblate.org/api/ = ${WEBLATE_API_KEY}
EOF
- name: Lock translations
run: |
wlc \
--url https://hosted.weblate.org/api/ \
lock \
actualbudget/actual
- name: Update VCS with latest translations
run: |
wlc \
--url https://hosted.weblate.org/api/ \
push \
actualbudget/actual
- name: Check out updated translations
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ssh-key: ${{ secrets.STRING_IMPORT_DEPLOY_KEY }}
repository: actualbudget/translations
path: translations
- name: Generate i18n strings
working-directory: actual
run: |
mkdir -p packages/desktop-client/locale/
cp ../translations/en.json packages/desktop-client/locale/
yarn generate:i18n
if [[ ! -f packages/desktop-client/locale/en.json ]]; then
echo "File packages/desktop-client/locale/en.json not found. Ensure the file was generated correctly."
exit 1
fi
- name: Check in new i18n strings
working-directory: translations
run: |
cp ../actual/packages/desktop-client/locale/en.json .
git add .
if git commit -m "Update source strings"; then
git push
else
echo "No changes to commit"
fi
- name: Update Weblate with latest translations
run: |
wlc \
--url https://hosted.weblate.org/api/ \
pull \
actualbudget/actual
- name: Unlock translations
if: always() # Clean up even on failure
run: |
wlc \
--url https://hosted.weblate.org/api/ \
unlock \
actualbudget/actual