Compare commits

...

3 Commits

Author SHA1 Message Date
Marijn d7e8d094cf fix: use global mailer From header for password reset email (#190)
Remove the hardcoded from address (info@tijdvoordetest.nl) so the
global headers.From in mailer.yaml is used instead, which includes the
"Tijd voor de test" display name and the correct noreply sender.
2026-07-08 08:10:57 +00:00
Marijn ba1e8d8eb6 ci: auto-trigger main CI when tagging a Dependabot commit (#188)
* ci: auto-trigger main CI run when tagging a Dependabot commit

Dependabot auto-merges use GITHUB_TOKEN which GitHub intentionally does
not re-trigger other workflows on. This means tagging those commits
immediately fails the verify-prior-run gate.

Instead of hard-failing, trigger ci.yml on main and wait for it to
succeed before proceeding with the deploy. Only triggers once; detects
and surfaces failures from the triggered run.

Bumps actions permission from read to write to allow workflow dispatch.

* ci: address CodeRabbit feedback on verify-prior-run job

Reduce max_attempts from 40 to 30 so worst-case runtime (15m) fits within
the 20-minute job timeout with margin. Trigger the fallback workflow run on
the tag ref instead of main so the dispatched run's head_sha matches the
tagged commit SHA that the polling loop is checking for.
2026-07-08 08:00:37 +00:00
Marijn 5d92d91432 fix: trust X-Forwarded-Proto header from Traefik proxy (#189)
Traefik terminates TLS and forwards requests over HTTP internally,
setting X-Forwarded-Proto: https. Without trusting this header,
Symfony generates http:// URLs (e.g. in password reset emails).
2026-07-08 07:45:07 +00:00
3 changed files with 27 additions and 7 deletions
+26 -4
View File
@@ -166,7 +166,7 @@ jobs:
timeout-minutes: 20 timeout-minutes: 20
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
permissions: permissions:
actions: read actions: write
steps: steps:
- name: Wait for and verify successful CI run on this commit - name: Wait for and verify successful CI run on this commit
env: env:
@@ -174,6 +174,8 @@ jobs:
run: | run: |
max_attempts=30 max_attempts=30
attempt=0 attempt=0
triggered=false
while [[ $attempt -lt $max_attempts ]]; do while [[ $attempt -lt $max_attempts ]]; do
attempt=$((attempt + 1)) attempt=$((attempt + 1))
@@ -191,12 +193,32 @@ jobs:
--jq "[.workflow_runs[] | select(.id != ${{ github.run_id }}) | select(.status == \"in_progress\" or .status == \"queued\" or .status == \"waiting\" or .status == \"requested\" or .status == \"pending\")] | length") --jq "[.workflow_runs[] | select(.id != ${{ github.run_id }}) | select(.status == \"in_progress\" or .status == \"queued\" or .status == \"waiting\" or .status == \"requested\" or .status == \"pending\")] | length")
if [[ "$in_progress_count" -gt 0 ]]; then if [[ "$in_progress_count" -gt 0 ]]; then
echo "CI still in progress (attempt $attempt/$max_attempts), waiting 30s..." echo "CI in progress (attempt $attempt/$max_attempts), waiting 30s..."
sleep 30 sleep 30
else continue
echo "::error::No prior successful CI run found for ${{ github.sha }}. Only tag commits that have passed CI on main." fi
if [[ "$triggered" == "false" ]]; then
echo "No prior CI run found for ${{ github.sha }}. Triggering CI on ${{ github.ref }}..."
gh workflow run ci.yml --repo "${{ github.repository }}" --ref "${{ github.ref }}"
triggered=true
echo "Triggered. Waiting 20s for run to register..."
sleep 20
continue
fi
failed_conclusion=$(gh api \
"repos/${{ github.repository }}/actions/workflows/ci.yml/runs?head_sha=${{ github.sha }}&per_page=10" \
--jq "[.workflow_runs[] | select(.id != ${{ github.run_id }}) | select(.status == \"completed\") | select(.conclusion != \"success\")] | first | .conclusion // empty" \
--raw-output)
if [[ -n "$failed_conclusion" ]]; then
echo "::error::Triggered CI run on main failed with conclusion: $failed_conclusion. Fix the issue before re-tagging."
exit 1 exit 1
fi fi
echo "Waiting for triggered run to register (attempt $attempt/$max_attempts)..."
sleep 20
done done
echo "::error::Timed out waiting for CI run to complete for ${{ github.sha }}." echo "::error::Timed out waiting for CI run to complete for ${{ github.sha }}."
+1 -1
View File
@@ -14,7 +14,7 @@ when@prod:
# shortcut for private IP address ranges of your proxy # shortcut for private IP address ranges of your proxy
trusted_proxies: 'private_ranges' trusted_proxies: 'private_ranges'
# or, if your proxy instead uses the "Forwarded" header # or, if your proxy instead uses the "Forwarded" header
trusted_headers: [ 'forwarded' ] trusted_headers: [ 'x-forwarded-proto' ]
when@test: when@test:
framework: framework:
@@ -11,7 +11,6 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
@@ -132,7 +131,6 @@ final class ResetPasswordController extends AbstractController
} }
$email = new TemplatedEmail() $email = new TemplatedEmail()
->from(new Address('info@tijdvoordetest.nl', 'Tijd voor de Test'))
->to($user->getUserIdentifier()) ->to($user->getUserIdentifier())
->subject($translator->trans('Your password reset request')) ->subject($translator->trans('Your password reset request'))
->htmlTemplate('reset_password/email.html.twig') ->htmlTemplate('reset_password/email.html.twig')