Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions .github/workflows/assets/submodule_ops.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ libs_submodule_names_from_gitmodules_file() {
| sed 's|^libs/||'
}

# Return 1 when .gitmodules has no libs/ submodule paths.
require_libs_submodules_in_gitmodules() {
local gitmodules_file="$1"
if ! libs_submodule_names_from_gitmodules_file "$gitmodules_file" | grep -q .; then
Comment thread
whisper67265 marked this conversation as resolved.
Outdated
phase_err "No libs/ submodules in .gitmodules. Run add-submodules first."
return 1
fi
}

# Fetch ${BOOST_ORG}/boost .gitmodules at ref; print raw content. Return 1 on failure.
fetch_boost_gitmodules_at_ref() {
local ref="$1"
Expand Down
23 changes: 11 additions & 12 deletions .github/workflows/start-translation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
# Jobs:
# setup — validate lang_codes and emit matrix JSON.
# sync-mirrors — sync mirror master for all submodules; update super-repo master.
# Zero libs/ entries in .gitmodules is a fatal precondition (run add-submodules first).
# On partial submodule failure: finalize successful pointers, then exit non-zero.
# start-local (matrix per lang) — local-{lang_code} in mirrors + super-repo + Weblate.
# Runs per language from setup when sync-mirrors produced successes (see job if:).
# Processes only submodules that succeeded in sync-mirrors.
# Runs per language when sync-mirrors succeeded (see job if:).
# Requires a non-empty updated_submodules handoff; empty array is a job failure.
#
# client_payload:
# lang_codes: (optional) Comma-separated lang codes (e.g. zh_Hans,ja). Defaults to vars.LANG_CODES.
Expand Down Expand Up @@ -129,14 +130,12 @@ jobs:
exit 1
}

mapfile -t submodule_names < <(libs_submodule_names_from_gitmodules_file ".gitmodules")

[[ ${#submodule_names[@]} -eq 0 ]] && {
echo "No libs/ submodules in .gitmodules, nothing to sync." >&2
echo "updated_submodules=[]" >> "$GITHUB_OUTPUT"
require_libs_submodules_in_gitmodules ".gitmodules" || {
end_phase
exit 0
exit 1
}

mapfile -t submodule_names < <(libs_submodule_names_from_gitmodules_file ".gitmodules")
end_phase

begin_phase "$PHASE_PROCESS_SUBMODULES" "Sync mirror master"
Expand Down Expand Up @@ -168,8 +167,8 @@ jobs:
fi

start-local:
# always() still evaluates outputs when sync-mirrors fails; updated_submodules is only set on full success.
if: ${{ always() && !cancelled() && needs.setup.result == 'success' && needs.sync-mirrors.outputs.updated_submodules != '' && needs.sync-mirrors.outputs.updated_submodules != '[]' }}
# Run when sync-mirrors succeeded; empty updated_submodules is a fatal error inside the job.
if: ${{ always() && !cancelled() && needs.setup.result == 'success' && needs.sync-mirrors.result == 'success' }}
needs: [setup, sync-mirrors]
runs-on: ubuntu-latest
strategy:
Expand Down Expand Up @@ -241,9 +240,9 @@ jobs:
mapfile -t submodule_names < <(parse_submodule_names_json "${SYNC_MIRROR_UPDATES:-[]}")

[[ ${#submodule_names[@]} -eq 0 ]] && {
echo "No submodules succeeded in sync-mirrors, nothing to process." >&2
phase_err "No submodules from sync-mirrors to process (updated_submodules is empty)."
end_phase
exit 0
exit 1
}
end_phase

Expand Down
14 changes: 10 additions & 4 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,16 @@ On partial submodule failure, **`sync-mirrors`** still finalizes successful subm
pointers in the super-repo via **`finalize_translations_master`**, then exits non-zero
when **`combine_batch_and_finalize_rc`** reports failure. In that case it does **not**
set the job output **`updated_submodules`** (only written when **`exit_rc == 0`**), so
**`start-local`** is skipped: its **`if:`** requires a non-empty **`updated_submodules`**
JSON array. Operators may expect partial mirror success to still hand off per-language
Weblate work, but the workflow gate requires **full** **`sync-mirrors`** success before
any **`start-local`** matrix job runs.
**`start-local`** is skipped: its **`if:`** requires **`sync-mirrors`** job success.
Operators may expect partial mirror success to still hand off per-language Weblate work,
but the workflow gate requires **full** **`sync-mirrors`** success before any
**`start-local`** matrix job runs.

**Precondition guards.** Zero **`libs/`** entries in this repo’s **`.gitmodules`** is a
fatal error in **`sync-mirrors`** (`Run add-submodules first.`). When **`sync-mirrors`**
succeeds but **`updated_submodules`** is an empty JSON array (all submodules non-fatally
skipped), **`start-local`** runs and exits non-zero with a distinct empty-handoff message
rather than silently succeeding.

### 6.4 Related conventions (not the batch 0/1/2 contract)

Expand Down
25 changes: 25 additions & 0 deletions tests/test_submodule_ops.bats
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,31 @@ EOF
[ "$output" = "json" ]
}

@test "require_libs_submodules_in_gitmodules: succeeds when libs/ paths exist" {
local gitmodules
gitmodules="$(mktemp)"
cat >"$gitmodules" <<'EOF'
[submodule "libs/json"]
path = libs/json
EOF
run require_libs_submodules_in_gitmodules "$gitmodules"
rm -f "$gitmodules"
[ "$status" -eq 0 ]
}

@test "require_libs_submodules_in_gitmodules: fails when no libs/ paths" {
local gitmodules
gitmodules="$(mktemp)"
cat >"$gitmodules" <<'EOF'
[submodule "other"]
path = other/path
EOF
run require_libs_submodules_in_gitmodules "$gitmodules"
rm -f "$gitmodules"
[ "$status" -eq 1 ]
[[ "$output" == *"Run add-submodules first."* ]]
}

@test "resolve_add_submodules_names: uses SUBMODULES when set" {
SUBMODULES="algorithm, system"
LIBS_REF="develop"
Expand Down