Complete staff translations and release verification
This commit is contained in:
parent
cf283db350
commit
4c52c8bf3d
|
|
@ -1978,3 +1978,14 @@ complete.
|
|||
- Production capacity, minimum CPU/RAM, database HA topology, and autoscaling
|
||||
thresholds remain unknown until representative target-environment
|
||||
measurements exist.
|
||||
# 2026-08-03 release-candidate quality gate
|
||||
|
||||
The isolated full repository quality run completed successfully on 2026-08-03.
|
||||
It covered shell, Compose, Helm, source-secret and infrastructure checks; Elixir
|
||||
format, compilation with warnings as errors, Gettext catalog freshness, xref,
|
||||
Credo, Sobelow, Dialyzer, Hex audit and the full ExUnit suite; pinned runtime
|
||||
image smoke tests and vulnerability scans; and production release, rollback and
|
||||
migration-policy drills. The transient Compose project, database volume and
|
||||
audit images were removed by the run's cleanup trap. This verifies the local
|
||||
candidate only; production browser E2E must be repeated after that candidate is
|
||||
promoted.
|
||||
|
|
|
|||
|
|
@ -974,8 +974,10 @@ defmodule WhoNeedHelpWeb.ModerationLive do
|
|||
</div>
|
||||
<span class="badge badge-outline">{status_label(proposal.mode)}</span>
|
||||
<span class={["badge", status_class(proposal.status)]}>{status_label(proposal.status)}</span>
|
||||
<span class="text-sm text-base-content/60">{gettext("%{count} votes",
|
||||
count: proposal.vote_count
|
||||
<span class="text-sm text-base-content/60">{ngettext(
|
||||
"%{count} vote",
|
||||
"%{count} votes",
|
||||
proposal.vote_count
|
||||
)}</span>
|
||||
<.icon name="hero-chevron-down" class="size-5 transition group-open:rotate-180" />
|
||||
</summary>
|
||||
|
|
|
|||
|
|
@ -112,9 +112,15 @@ defmodule WhoNeedHelpWeb.SupportOperationLive do
|
|||
end
|
||||
|
||||
defp assignment_options(users) do
|
||||
[{gettext("Unassigned"), ""} | Enum.map(users, &{&1.display_name || &1.email, &1.id})]
|
||||
[{gettext("Unassigned"), ""} | Enum.map(users, &{staff_identity_label(&1), &1.id})]
|
||||
end
|
||||
|
||||
defp staff_identity_label(%{display_name: name, email: email})
|
||||
when is_binary(name) and name != "" and name != email,
|
||||
do: gettext("%{name} — %{email}", name: name, email: email)
|
||||
|
||||
defp staff_identity_label(%{email: email}), do: email
|
||||
|
||||
defp queue_path(:support), do: ~p"/support/operations?queue=support"
|
||||
defp queue_path(:legal), do: ~p"/support/operations?queue=legal"
|
||||
|
||||
|
|
|
|||
|
|
@ -231,10 +231,16 @@ defmodule WhoNeedHelpWeb.SupportOperationsLive do
|
|||
{gettext("Any assignee"), ""},
|
||||
{gettext("Unassigned"), "unassigned"},
|
||||
{gettext("Assigned to me"), "mine"}
|
||||
| Enum.map(users, fn user -> {user.display_name || user.email, user.id} end)
|
||||
| Enum.map(users, fn user -> {staff_identity_label(user), user.id} end)
|
||||
]
|
||||
end
|
||||
|
||||
defp staff_identity_label(%{display_name: name, email: email})
|
||||
when is_binary(name) and name != "" and name != email,
|
||||
do: gettext("%{name} — %{email}", name: name, email: email)
|
||||
|
||||
defp staff_identity_label(%{email: email}), do: email
|
||||
|
||||
defp support_kind(:account_access), do: gettext("Account access")
|
||||
defp support_kind(:technical_issue), do: gettext("Technical issue")
|
||||
defp support_kind(:safety_concern), do: gettext("Safety concern")
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -167,16 +167,19 @@ git cat-file -e "$commit^{commit}" 2>/dev/null || {
|
|||
exit 1
|
||||
}
|
||||
|
||||
while IFS= read -r changed_path; do
|
||||
case "$changed_path" in
|
||||
lib/mix/tasks/wnh.staging_full_e2e.ex | e2e/tests/activity-moderation.spec.ts | e2e/tests/helpers.ts | test/who_need_help/trust_safety_test.exs)
|
||||
;;
|
||||
*)
|
||||
echo "Production E2E refused: unexpected local change relative to $commit: $changed_path" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < <(git diff --name-only "$commit")
|
||||
# The deployed application is always archived from its exact remote commit.
|
||||
# Local development may legitimately be ahead of production; those files never
|
||||
# enter either runner image. Only these explicit verifier overlays are copied
|
||||
# below, and their hashes are retained with the evidence bundle.
|
||||
for verifier_path in \
|
||||
lib/mix/tasks/wnh.staging_full_e2e.ex \
|
||||
e2e/tests/activity-moderation.spec.ts \
|
||||
e2e/tests/helpers.ts; do
|
||||
if [[ ! -f "$ROOT/$verifier_path" ]]; then
|
||||
echo "Production E2E verifier is unavailable: $verifier_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
confirmation="whoneedhelp.com:${commit}:${database}:${RUN_ID}:full-browser-e2e"
|
||||
|
||||
|
|
|
|||
|
|
@ -1463,6 +1463,7 @@ echo "Running Elixir format, compiler, xref, Credo, Sobelow, Dialyzer, and Hex a
|
|||
docker run --rm "$quality_image" sh -euc '
|
||||
mix format --check-formatted
|
||||
mix compile --force --warnings-as-errors
|
||||
mix gettext.extract --check-up-to-date
|
||||
mix xref graph --label compile-connected --fail-above 0
|
||||
mix credo --strict --min-priority high
|
||||
mix sobelow --exit --strict --private --skip
|
||||
|
|
|
|||
|
|
@ -407,6 +407,18 @@ defmodule WhoNeedHelpWeb.SupportControllerTest do
|
|||
test "renders separate support and removal queues for a moderator", %{conn: conn} do
|
||||
moderator = staff_user_fixture([:support, :legal])
|
||||
|
||||
first_duplicate =
|
||||
staff_user_fixture([:support, :legal],
|
||||
display_name: "Same operator",
|
||||
email: unique_user_email()
|
||||
)
|
||||
|
||||
second_duplicate =
|
||||
staff_user_fixture([:support, :legal],
|
||||
display_name: "Same operator",
|
||||
email: unique_user_email()
|
||||
)
|
||||
|
||||
{:ok, support_request} =
|
||||
WhoNeedHelp.Support.create_request(nil, %{
|
||||
"kind" => "technical_issue",
|
||||
|
|
@ -447,6 +459,8 @@ defmodule WhoNeedHelpWeb.SupportControllerTest do
|
|||
|
||||
assert response =~ "Support requests"
|
||||
assert response =~ "Legal and removal"
|
||||
assert response =~ "Same operator — #{first_duplicate.email}"
|
||||
assert response =~ "Same operator — #{second_duplicate.email}"
|
||||
assert has_element?(queue_view, "#support-row-#{support_request.id}")
|
||||
refute response =~ "Operator action"
|
||||
|
||||
|
|
@ -471,6 +485,8 @@ defmodule WhoNeedHelpWeb.SupportControllerTest do
|
|||
) == 1
|
||||
|
||||
assert has_element?(removal_view, "#removal-moderation-#{removal_notice.id}")
|
||||
assert removal_response =~ "Same operator — #{first_duplicate.email}"
|
||||
assert removal_response =~ "Same operator — #{second_duplicate.email}"
|
||||
|
||||
assert Enum.count(
|
||||
LazyHTML.query(
|
||||
|
|
|
|||
|
|
@ -1556,12 +1556,14 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
|
|||
"message_id" => message.id
|
||||
})
|
||||
|
||||
{:ok, _proposal} =
|
||||
{:ok, proposal} =
|
||||
Catalog.propose(user_scope_fixture(requester), %{
|
||||
"proposed_name" => "Bicycle repair",
|
||||
"reason" => "Urgent roadside bicycle repairs need a reusable category."
|
||||
})
|
||||
|
||||
{:ok, _vote} = Catalog.vote(user_scope_fixture(requester), proposal.id)
|
||||
|
||||
{:ok, view, html} = live(conn, ~p"/moderation")
|
||||
assert html =~ "Trust and safety"
|
||||
assert html =~ "Reports"
|
||||
|
|
@ -1592,6 +1594,8 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do
|
|||
|
||||
proposal_html = render_patch(view, ~p"/moderation?queue=proposals")
|
||||
assert proposal_html =~ "Bicycle repair"
|
||||
assert proposal_html =~ "1 vote"
|
||||
refute proposal_html =~ "1 votes"
|
||||
end
|
||||
|
||||
test "message reports expose parent activity moderation and switch to restore", %{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user