Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
3890216
feat: setup react-email for html emails
cyyynthia Nov 12, 2023
bdd12a2
chore: upgrade email subproject
cyyynthia Nov 16, 2024
23f93f8
feat: configure CLI, write quick extractor
cyyynthia Nov 17, 2024
e44d8fd
feat: rough first implementation of emails in backend
cyyynthia Nov 17, 2024
8d6f731
fix: lint, try to troubleshoot test failures
cyyynthia Nov 20, 2024
114b078
fix: properly render strings using icu4j
cyyynthia Nov 23, 2024
edf84aa
feat: render icu xml as fragments
cyyynthia Jun 9, 2025
dee3880
feat: finalize working impl of react emails renderer
cyyynthia Jun 9, 2025
f5eed37
feat: implement global variables
cyyynthia Jun 9, 2025
587c27d
fix: properly implement sanitization in Var
cyyynthia Jun 9, 2025
aa907c0
chore: minor adjustments
cyyynthia Jun 16, 2025
7b7ba88
chore: typo in CI config
cyyynthia Jun 16, 2025
d16888b
chore: fix accidentally introduced tab indents
cyyynthia Jun 16, 2025
9e15a8d
chore: fix typo part 2
cyyynthia Jun 16, 2025
90e6132
chore: please the artificial rabbit
cyyynthia Jun 16, 2025
d8ab33d
chore: misc fixes and improvements
cyyynthia Jun 17, 2025
06af1f9
chore: lint
cyyynthia Jun 17, 2025
ee26c3a
fix: proper path in gha config
cyyynthia Jun 17, 2025
00e0d72
chore: refactor
cyyynthia Jun 17, 2025
9ab41f8
chore: minor improvement of EmailTemplateConfig
cyyynthia Jun 17, 2025
a1a8ec9
chore: gradle config
cyyynthia Jun 17, 2025
17c05bd
chore: gradle config pt. 2
cyyynthia Jun 17, 2025
2d98490
chore: gradle config pt. 3
cyyynthia Jun 18, 2025
4040a63
chore: gradle config pt. 3.1
cyyynthia Jun 18, 2025
b2429c0
chore: gradle config pt. 3.2
cyyynthia Jun 18, 2025
1a5cf27
chore: gha tweaks (again)
cyyynthia Jun 20, 2025
b811141
chore: silly gha mistakes
cyyynthia Jun 20, 2025
6a1c3f7
ci: mixed up src/dest actions
cyyynthia Jun 20, 2025
47d43e8
fix: a small typo for a file, a giant failure for gradle build
cyyynthia Jul 7, 2025
34c270f
feat: React Emails > default template (#3194)
JanCizmar Oct 17, 2025
747e143
chore: rebase
dkrizan Oct 17, 2025
4253bab
fix: invitation link getter in cypress
dkrizan Oct 17, 2025
14cacc9
chore: dont pull translations for emails
dkrizan Oct 27, 2025
ff4f16e
chore: coderabbit changes
dkrizan Oct 29, 2025
041a81d
chore: ktlint format
dkrizan Jan 8, 2026
7b47c04
chore: missing imports fix
dkrizan Jan 8, 2026
60023cb
chore: coderabbit changes
dkrizan Jan 9, 2026
efbb844
chore: coderabbit changes
dkrizan Jan 9, 2026
4d8cda3
chore: enhance e2e tasks with finalizedBy and output stream handling
dkrizan Jan 9, 2026
14f4e09
chore: improve accessibility for social links in ClassicLayout
dkrizan Jan 9, 2026
c10c511
chore: remove aria-hidden attribute from email image test
dkrizan Jan 9, 2026
6787212
chore: rollback unrelated gha changes
dkrizan Jan 9, 2026
979c0d8
chore: gha final
dkrizan Jan 13, 2026
00df861
chore: increase backend startup timeout in test workflow
dkrizan Feb 20, 2026
06ffbc7
fix: address review issues in react-email PR
dkrizan Feb 27, 2026
a2e3c94
fix: address coderabbit review issues
dkrizan Mar 4, 2026
f7eb270
fix: address review comments
dkrizan Mar 6, 2026
aa0a763
chore: rename SRC_DIR/DEST_DIR to BASE_DIR in build actions
dkrizan Mar 7, 2026
c681207
chore: axllent/mailpit updated
dkrizan Mar 9, 2026
d28081c
chore: revert unrelated release workflow changes
dkrizan Mar 9, 2026
d3fd222
fix: validate SMTP configuration on startup
dkrizan Mar 11, 2026
bd4d491
fix: replace @MockBean with @MockitoBean and improve test configurations
dkrizan Mar 12, 2026
28b6c35
test: add email template rendering tests for various scenarios
dkrizan Mar 15, 2026
3358b2f
refactor: parametrize duplicate build email Gradle tasks
dkrizan Mar 18, 2026
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
32 changes: 20 additions & 12 deletions .github/actions/download-backend-build/action.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Download backend build
description: Download backend build from GitHub artifacts and decompress them

inputs:
base-directory:
description: Base directory for the backend build. Defaults to current working directory.
default: .

runs:
using: composite
steps:
Expand All @@ -10,16 +15,19 @@ runs:
name: backend
path: ~/

- name: Un-tar build results
shell: sh
- name: Decompress build results
shell: bash
env:
BASE_DIR: ${{ inputs.base-directory }}
run: |
tar --zstd -xf ~/backend-api.tar.zst ./backend/api/build
tar --zstd -xf ~/backend-app.tar.zst ./backend/app/build
tar --zstd -xf ~/backend-data.tar.zst ./backend/data/build
tar --zstd -xf ~/backend-misc.tar.zst ./backend/misc/build
tar --zstd -xf ~/backend-security.tar.zst ./backend/security/build
tar --zstd -xf ~/backend-testing.tar.zst ./backend/testing/build
tar --zstd -xf ~/backend-ktlint.tar.zst ./backend/ktlint/build
tar --zstd -xf ~/backend-development.tar.zst ./backend/development/build
tar --zstd -xf ~/ee-backend-app.tar.zst ./ee/backend/app/build
tar --zstd -xf ~/ee-backend-tests.tar.zst ./ee/backend/tests/build
tar --zstd -xf ~/backend-api.tar.zst $BASE_DIR/backend/api/build
tar --zstd -xf ~/backend-app.tar.zst $BASE_DIR/backend/app/build
tar --zstd -xf ~/backend-data.tar.zst $BASE_DIR/backend/data/build
tar --zstd -xf ~/backend-misc.tar.zst $BASE_DIR/backend/misc/build
tar --zstd -xf ~/backend-security.tar.zst $BASE_DIR/backend/security/build
tar --zstd -xf ~/backend-testing.tar.zst $BASE_DIR/backend/testing/build
tar --zstd -xf ~/backend-ktlint.tar.zst $BASE_DIR/backend/ktlint/build
tar --zstd -xf ~/backend-development.tar.zst $BASE_DIR/backend/development/build
tar --zstd -xf ~/ee-backend-app.tar.zst $BASE_DIR/ee/backend/app/build
tar --zstd -xf ~/ee-backend-tests.tar.zst $BASE_DIR/ee/backend/tests/build
tar --zstd -xf ~/backend-email.tar.zst $BASE_DIR/email/out
38 changes: 37 additions & 1 deletion .github/actions/setup-env/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,21 @@ inputs:
description: Whether to setup Node.js or not.
default: "true"
npm-cache:
description: Whether to setup npm cache or not.
description: Whether to setup npm cache or not. Irrelevant if node is disabled.
default: "true"
docker:
description: Whether to setup additional Docker build environment tools. Defaults to false.
default: "false"
docker-ghcr:
description: Whether to login to the GitHub Container Registry or not. Defaults to false.
default: "false"
docker-hub:
description: Whether to login to Docker Hub or not. Defaults to false.
default: "false"
docker-hub-username:
description: Username to use to authenticate to Docker Hub.
docker-hub-password:
description: Password to use to authenticate to Docker Hub.

runs:
using: composite
Expand Down Expand Up @@ -40,3 +53,26 @@ runs:
key: cache-node-modules-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
cache-node-modules-${{ runner.os }}-

- name: Setup QEMU for Docker
if: "${{ inputs.docker == 'true' }}"
uses: docker/setup-qemu-action@v3

- name: Setup Docker Buildx
if: "${{ inputs.docker == 'true' }}"
uses: docker/setup-buildx-action@v3

- name: Login to Docker Hub
if: "${{ inputs.docker-hub == 'true' }}"
uses: docker/login-action@v3
with:
username: ${{ inputs.docker-hub-username }}
password: ${{ inputs.docker-hub-password }}

- name: Login to GitHub Container Registry
if: "${{ inputs.docker-ghcr == 'true' }}"
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
36 changes: 23 additions & 13 deletions .github/actions/upload-backend-build/action.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
name: Upload backend build
description: Compress and upload backend build result to GitHub artifacts

inputs:
base-directory:
description: Base directory for the backend build. Defaults to current working directory.
default: .

runs:
using: composite
steps:
- name: Compress build assets
shell: sh
- name: Compress build results
shell: bash
env:
BASE_DIR: ${{ inputs.base-directory }}
run: |
tar --zstd -cf ~/backend-api.tar.zst ./backend/api/build
tar --zstd -cf ~/backend-app.tar.zst ./backend/app/build
tar --zstd -cf ~/backend-data.tar.zst ./backend/data/build
tar --zstd -cf ~/backend-misc.tar.zst ./backend/misc/build
tar --zstd -cf ~/backend-security.tar.zst ./backend/security/build
tar --zstd -cf ~/backend-testing.tar.zst ./backend/testing/build
tar --zstd -cf ~/backend-ktlint.tar.zst ./backend/ktlint/build
tar --zstd -cf ~/backend-development.tar.zst ./backend/development/build
tar --zstd -cf ~/ee-backend-app.tar.zst ./ee/backend/app/build
tar --zstd -cf ~/ee-backend-tests.tar.zst ./ee/backend/tests/build
tar --zstd -cf ~/backend-api.tar.zst $BASE_DIR/backend/api/build
tar --zstd -cf ~/backend-app.tar.zst $BASE_DIR/backend/app/build
tar --zstd -cf ~/backend-data.tar.zst $BASE_DIR/backend/data/build
tar --zstd -cf ~/backend-misc.tar.zst $BASE_DIR/backend/misc/build
tar --zstd -cf ~/backend-security.tar.zst $BASE_DIR/backend/security/build
tar --zstd -cf ~/backend-testing.tar.zst $BASE_DIR/backend/testing/build
tar --zstd -cf ~/backend-ktlint.tar.zst $BASE_DIR/backend/ktlint/build
tar --zstd -cf ~/backend-development.tar.zst $BASE_DIR/backend/development/build
tar --zstd -cf ~/ee-backend-app.tar.zst $BASE_DIR/ee/backend/app/build
tar --zstd -cf ~/ee-backend-tests.tar.zst $BASE_DIR/ee/backend/tests/build
tar --zstd -cf ~/backend-email.tar.zst $BASE_DIR/email/out

- uses: actions/upload-artifact@v4
- name: Upload backend build result
uses: actions/upload-artifact@v4
with:
name: backend
path: |
Expand All @@ -32,3 +41,4 @@ runs:
~/backend-development.tar.zst
~/ee-backend-app.tar.zst
~/ee-backend-tests.tar.zst
~/backend-email.tar.zst
13 changes: 9 additions & 4 deletions .github/workflows/prerelease-alpha.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,21 @@ jobs:
if: ${{ steps.version.outputs.VERSION != '' }}
run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p "${{ secrets.DOCKERHUB_PASSWORD }}"

- name: Create docker image
- name: Prepare for docker build
if: ${{ steps.version.outputs.VERSION != '' }}
run: |
docker buildx create --use
./gradlew dockerPublish
run: ./gradlew dockerPrepare
env:
VERSION: ${{ steps.version.outputs.VERSION }}
TOLGEE_API_KEY: ${{secrets.TOLGEE_API_KEY}}
TOLGEE_API_URL: ${{secrets.TOLGEE_API_URL}}

- name: Create docker image
if: ${{ steps.version.outputs.VERSION != '' }}
run: |
docker buildx create --use
docker buildx build . -t tolgee/tolgee:${{ steps.version.outputs.VERSION }} --platform linux/arm64,linux/amd64 --push
working-directory: build/docker

- name: Pack with webapp
if: ${{ steps.version.outputs.VERSION != '' }}
run: ./gradlew packResources
Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,18 @@ jobs:
id: version
run: echo "VERSION=$(echo $GITHUB_REF | sed -e 's/refs\/tags\///g' -e 's/\//-/g')" >> $GITHUB_OUTPUT

- name: Create docker image
run: |
docker buildx create --use
./gradlew dockerPublish
- name: Prepare for docker build
run: ./gradlew dockerPrepare
env:
VERSION: ${{ steps.version.outputs.VERSION }}
DOCKER_IMAGE: tgint/tgpreview
TOLGEE_API_KEY: ${{secrets.TOLGEE_API_KEY}}
TOLGEE_API_URL: ${{secrets.TOLGEE_API_URL}}

- name: Create docker image
run: |
docker buildx create --use
docker buildx build . -t tgint/tgpreview:${{ steps.version.outputs.VERSION }} --platform linux/arm64,linux/amd64 --push
working-directory: build/docker

- name: Deploy
uses: nickgronow/kubectl@master
with:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/reportIntermittentTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
./gradlew ${{ matrix.command.run }};
env:
SKIP_SERVER_BUILD: true
SKIP_EMAIL_BUILD: true

- name: Get report name
id: reportName
Expand Down Expand Up @@ -135,6 +136,7 @@ jobs:
TOLGEE_API_URL: ${{secrets.TOLGEE_API_URL}}
SKIP_WEBAPP_BUILD: true
SKIP_SERVER_BUILD: true
SKIP_EMAIL_BUILD: true
SKIP_INSTALL_E2E_DEPS: true
E2E_TOTAL_JOBS: ${{matrix.total_jobs}}
E2E_JOB_INDEX: ${{matrix.job_index}}
Expand Down
35 changes: 33 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ jobs:

# Don't build test classes here; they'll only be used once during the test run anyway.
# This amortizes the cost of compilation across each test job, rather than paying it upfront.
# Test emails are built nonetheless, as they may be used by multiple subprojects...
#
# Note: seems like running in parallel has the weird side effect of causing Spring dependency management to hang
# It's very occasional, and doesn't seem to occur locally, but parallel being the issue is possible
# See: https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/370
- name: Build backend
run: ./gradlew classes jar bootJar
run: ./gradlew classes jar bootJar buildTestEmails

- name: Upload backend build result
uses: ./.github/actions/upload-backend-build
Expand Down Expand Up @@ -71,6 +72,7 @@ jobs:
command: ./gradlew ${{ matrix.command }}
env:
SKIP_SERVER_BUILD: true
SKIP_EMAIL_BUILD: true
CI_RELEASE: ${{ github.event_name == 'push' && true || false }}

- name: Get report name
Expand Down Expand Up @@ -176,6 +178,7 @@ jobs:
TOLGEE_API_URL: ${{secrets.TOLGEE_API_URL}}
SKIP_WEBAPP_BUILD: true
SKIP_SERVER_BUILD: true
SKIP_EMAIL_BUILD: true
SKIP_INSTALL_E2E_DEPS: true
E2E_TOTAL_JOBS: ${{matrix.total_jobs}}
E2E_JOB_INDEX: ${{matrix.job_index}}
Expand Down Expand Up @@ -297,7 +300,7 @@ jobs:
run: |
./gradlew server-app:bootRun --args='--spring.profiles.active=dev' &
echo "Waiting for backend to start..."
timeout 120 bash -c 'until curl -s http://localhost:8080/actuator/health > /dev/null 2>&1; do sleep 2; done'
timeout 180 bash -c 'until curl -s http://localhost:8080/actuator/health > /dev/null 2>&1; do sleep 2; done'
echo "Backend is ready"
env:
SKIP_SERVER_BUILD: true
Expand Down Expand Up @@ -454,12 +457,36 @@ jobs:
- name: Run ktlint
run: ./gradlew ktlintCheck

email-code-checks:
name: Email templates static check 🪲
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4

- name: Setup environment
uses: ./.github/actions/setup-env
with:
java: 'false'

- name: Install dependencies
run: npm ci
working-directory: ./email

- name: TypeScript
run: npm run tsc
working-directory: ./email

- name: ESLint
run: npm run eslint
working-directory: ./email

everything-passed:
name: Everything passed 🎉
needs:
- backend-build
- backend-test
- backend-code-checks
- email-code-checks
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- frontend-build
- frontend-code-check
- schema-check
Expand Down Expand Up @@ -519,6 +546,10 @@ jobs:
failed_jobs+=("e2e-install-deps")
fi

if [[ "${{ needs.email-code-checks.result }}" != "success" ]]; then
failed_jobs+=("email-code-checks")
fi

if [[ "${#failed_jobs[@]}" -gt 0 ]]; then
echo "The following jobs failed: ${failed_jobs[*]}"
exit 1
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

4 changes: 4 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ To learn more about externalized configuration in Spring boot, read [the docs](h

Since we set the active profile to `dev`, Spring uses the `application-dev.yaml` configuration file.

## Writing emails

Please refer to [email/HACKING.md](email/HACKING.md).

## Updating the database changelog

Tolgee uses Liquibase to handle the database migration. The migrations are run on every app startup. To update the changelog, run:
Expand Down
6 changes: 1 addition & 5 deletions backend/api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ apply plugin: "org.jetbrains.kotlin.plugin.spring"
apply plugin: "kotlin-allopen"
apply plugin: 'io.spring.dependency-management'

repositories {
mavenCentral()
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
Expand Down Expand Up @@ -102,6 +98,6 @@ dependencyManagement {
}
}

jar {
tasks.named('jar', Jar) {
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,12 @@ class ResetPasswordRequestHandler(
EmailParams(
to = request.email,
subject = if (isInitial) "Initial password configuration" else "Password reset",
header = "Password reset",
Comment thread
dkrizan marked this conversation as resolved.
text =
"""
Hello! 👋<br/><br/>
${if (isInitial) "To set a password for your account, <b>follow this link</b>:<br/>" else "To reset your password, <b>follow this link</b>:<br/>"}
<a href="$url">$url</a><br/><br/>
If you have not requested this e-mail, please ignore it.<br/><br/>

Regards,<br/>
Tolgee
""".trimIndent(),
)

Expand All @@ -67,15 +64,12 @@ class ResetPasswordRequestHandler(
EmailParams(
to = request.email,
subject = "Password reset - SSO managed account",
header = "Password reset",
text =
"""
Hello! 👋<br/><br/>
We received a request to reset the password for your account. However, your account is managed by your organization and uses a single sign-on (SSO) service to log in.<br/><br/>
To access your account, please use the "SSO Login" button on the Tolgee login page. No password reset is needed.<br/><br/>
If you did not make this request, you may safely ignore this email.<br/><br/>

Regards,<br/>
Tolgee
""".trimIndent(),
)

Expand Down
Loading
Loading