Skip to content

Pull and clean properties #178

Pull and clean properties

Pull and clean properties #178

name: Pull and clean properties
on:
workflow_dispatch: {}
schedule:
- cron: "0 0,12 * * *" # every day at 00:00 and 12:00 UTC
permissions:
contents: write
pull-requests: write
concurrency:
group: pull-and-clean-${{ github.ref }}
cancel-in-progress: false
jobs:
pull-clean:
runs-on: ubuntu-latest
env:
TX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }}
GH_PAT: ${{ secrets.GH_PAT }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
# Avoid using GITHUB_TOKEN for pushes; we'll use GH_PAT instead so downstream workflows trigger
persist-credentials: false
- name: Ensure GH_PAT is provided (required to trigger downstream workflows)
run: |
if [ -z "${GH_PAT:-}" ]; then
echo "GH_PAT secret is not set. This job requires a PAT with 'repo' and 'workflow' scopes so that pushes and PR creation trigger other workflows (like lint)." >&2
exit 1
fi
- name: Configure push auth (use GH_PAT)
run: |
git remote set-url origin https://x-access-token:${{ env.GH_PAT }}@github.com/${{ github.repository }}
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Install Transifex CLI (Go)
run: |
curl -sSfL https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
# Move the tx binary into a directory on PATH for subsequent steps
mkdir -p "$HOME/bin"
install -m 0755 ./tx "$HOME/bin/tx"
echo "$HOME/bin" >> "$GITHUB_PATH"
command -v tx || true
tx --version || true
- name: Configure Transifex credentials
run: |
if [ -z "${TX_TOKEN:-}" ]; then
echo "TRANSIFEX_TOKEN secret is not set" >&2
exit 1
fi
mkdir -p "$HOME"
printf "%s\n" \
"[https://app.transifex.com]" \
"hostname = https://app.transifex.com" \
"api_hostname = https://api.transifex.com" \
"token = ${TX_TOKEN}" > "$HOME/.transifexrc"
chmod 600 "$HOME/.transifexrc"
echo "Created ~/.transifexrc"
- name: Verify Transifex CLI
run: tx --version
- name: Configure Git user
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Prepare transifex branch (hard reset to main)
id: prep
run: |
set -euo pipefail
git fetch origin main transifex || true
if git ls-remote --exit-code --heads origin transifex >/dev/null 2>&1; then
git checkout -B transifex origin/transifex
prev_sha=$(git rev-parse HEAD)
{ echo "previous_sha=${prev_sha}"; } >> "$GITHUB_OUTPUT"
# Try to merge main; if conflicts, abort and hard reset to origin/main
if git merge --no-ff --no-edit origin/main; then
{
echo "branch_state=existing"
echo "merge_strategy=merged_clean"
echo "did_merge=true"
echo "did_reset=false"
} >> "$GITHUB_OUTPUT"
else
echo "Merge had conflicts; aborting and resetting to origin/main"
git merge --abort || true
git reset --hard origin/main
{
echo "branch_state=existing"
echo "merge_strategy=reset_due_to_conflicts"
echo "did_merge=false"
echo "did_reset=true"
} >> "$GITHUB_OUTPUT"
fi
else
echo "Creating transifex branch from origin/main"
{
echo "previous_sha=none"
echo "branch_state=created"
echo "merge_strategy=created_from_main"
echo "did_merge=false"
echo "did_reset=false"
} >> "$GITHUB_OUTPUT"
git checkout -B transifex origin/main
fi
- name: Make scripts executable
run: chmod +x .github/scripts/pull_and_clean_properties.sh
- name: Run pull_and_clean_properties.sh
run: bash .github/scripts/pull_and_clean_properties.sh
- name: Commit and push changes (if any)
id: commit
run: |
set -euo pipefail
if [ -n "$(git status --porcelain)" ]; then
current_branch=$(git branch --show-current)
if [ "$current_branch" != "transifex" ]; then
git checkout transifex
fi
git add -A
git commit -m "Transifex: pull and normalize .properties via CI"
git push -f origin transifex
echo "Changes pushed to transifex branch."
echo "changes=true" >> "$GITHUB_OUTPUT"
else
echo "No changes to commit."
echo "changes=false" >> "$GITHUB_OUTPUT"
fi
- name: Generate outputs report
id: report
run: |
set -euo pipefail
tx_version=$(tx --version 2>/dev/null || echo "unknown")
{
echo "tx_version=${tx_version}"
echo "previous_sha=${{ steps.prep.outputs.previous_sha }}"
echo "branch_state=${{ steps.prep.outputs.branch_state }}"
} >> "$GITHUB_OUTPUT"
if [ "${{ steps.commit.outputs.changes }}" = "true" ]; then
commit_sha=$(git rev-parse HEAD)
short_sha=${commit_sha:0:7}
commit_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/commit/${commit_sha}"
files_changed=$(git diff --name-only HEAD^ HEAD | wc -l | tr -d ' ')
shortstat=$(git diff --shortstat HEAD^ HEAD | sed 's/^ *//')
{
echo "commit_sha=${commit_sha}"
echo "files_changed=${files_changed}"
echo "diffstat=${shortstat}"
} >> "$GITHUB_OUTPUT"
{
echo "### Transifex run report"
echo "- tx version: ${tx_version}"
echo "- previous head: ${{ steps.prep.outputs.previous_sha }} (${{ steps.prep.outputs.branch_state }})"
echo "- merge strategy: ${{ steps.prep.outputs.merge_strategy }}"
echo "- did merge: ${{ steps.prep.outputs.did_merge }}"
echo "- did reset: ${{ steps.prep.outputs.did_reset }}"
echo "- new commit: [${short_sha}](${commit_url})"
echo "- changes: ${files_changed} files (${shortstat})"
} >> "$GITHUB_STEP_SUMMARY"
else
{
echo "commit_sha=none"
echo "files_changed=0"
echo "diffstat=none"
} >> "$GITHUB_OUTPUT"
{
echo "### Transifex run report"
echo "- tx version: ${tx_version}"
echo "- previous head: ${{ steps.prep.outputs.previous_sha }} (${{ steps.prep.outputs.branch_state }})"
echo "- merge strategy: ${{ steps.prep.outputs.merge_strategy }}"
echo "- did merge: ${{ steps.prep.outputs.did_merge }}"
echo "- did reset: ${{ steps.prep.outputs.did_reset }}"
echo "- changes: none"
} >> "$GITHUB_STEP_SUMMARY"
fi
- name: Check differences between transifex and main
id: diff
run: |
set -euo pipefail
git fetch origin main transifex || true
if git ls-remote --exit-code --heads origin transifex >/dev/null 2>&1; then
if git diff --quiet origin/main..origin/transifex; then
{ echo "differs=false"; } >> "$GITHUB_OUTPUT"
echo "No differences between origin/transifex and origin/main"
else
{ echo "differs=true"; } >> "$GITHUB_OUTPUT"
echo "Differences detected between origin/transifex and origin/main"
fi
else
{ echo "differs=false"; } >> "$GITHUB_OUTPUT"
echo "origin/transifex does not exist; skipping PR creation"
fi
- name: Open PR to main if differences (PAT)
if: steps.diff.outputs.differs == 'true' && env.GH_PAT != ''
id: openpr
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_PAT }}
script: |
const { owner, repo } = context.repo;
const head = 'transifex';
const base = 'main';
const list = await github.rest.pulls.list({ owner, repo, state: 'open', base, head: `${owner}:${head}` });
if (list.data.length > 0) {
core.info('An open PR from transifex to main already exists.');
const pr = list.data[0];
core.setOutput('pr_state', 'existed');
core.setOutput('pr_number', String(pr.number));
core.setOutput('pr_url', pr.html_url);
} else {
const prev = `${{ steps.prep.outputs.previous_sha }}`;
const didReset = `${{ steps.prep.outputs.did_reset }}` === 'true';
const didMerge = `${{ steps.prep.outputs.did_merge }}` === 'true';
let prevLine;
if (prev && prev !== 'none') {
if (didReset) prevLine = `Previous transifex head (before reset): ${prev}`;
else if (didMerge) prevLine = `Previous transifex head (before merge): ${prev}`;
else prevLine = `Previous transifex head: ${prev}`;
} else {
prevLine = 'Branch was created from main (no previous head).';
}
const body = [
'Automated update of .properties files via CI.',
'',
prevLine
].join('\n');
const created = await github.rest.pulls.create({ owner, repo, head, base, title: 'Transifex: update properties', body });
core.info('Opened PR from transifex to main.');
core.setOutput('pr_state', 'created');
core.setOutput('pr_number', String(created.data.number));
core.setOutput('pr_url', created.data.html_url);
}
- name: Append PR status to summary
if: always()
run: |
{
echo "### PR status";
if [ "${{ steps.diff.outputs.differs }}" = "true" ]; then
if [ "${{ steps.openpr.outputs.pr_state }}" = "created" ]; then
echo "- PR created: ${{ steps.openpr.outputs.pr_url }}";
elif [ "${{ steps.openpr.outputs.pr_state }}" = "existed" ]; then
echo "- PR already existed: ${{ steps.openpr.outputs.pr_url }}";
else
if [ -z "${{ env.GH_PAT }}" ]; then
echo "- Differences found, but GH_PAT not set; PR not created.";
else
echo "- Differences found, but PR was not created (step skipped or failed).";
fi
fi
else
echo "- No differences between 'transifex' and 'main'; no PR needed.";
fi
} >> "$GITHUB_STEP_SUMMARY"