feat(preview): deterministic per-PR preview domains via ${prNumber} template variable#4766
Open
fidelis05 wants to merge 2 commits into
Open
feat(preview): deterministic per-PR preview domains via ${prNumber} template variable#4766fidelis05 wants to merge 2 commits into
fidelis05 wants to merge 2 commits into
Conversation
Preview deployments generate their domain by substituting the app's
"Wildcard Domain" setting. Previously the only supported token was the
"*" wildcard, which is replaced with a hash that always includes a
random suffix, so the resulting domain is not predictable ahead of time.
Add a ${prNumber} template variable, already available from the pull
request that triggers the deployment, so users can build a domain that
is deterministic per PR (e.g. frontend-pr${prNumber}.example.com). This
lets a sibling service in the same PR reference this app's preview URL
before it has been deployed. ${prNumber} can be combined with "*" to
keep per-app uniqueness (e.g. *.pr-${prNumber}.example.com).
The wildcard generator is renamed to generatePreviewWildcardDomain and
exported (it previously collided with an unrelated generateWildcardDomain
in services/domain.ts) so its pure substitution logic can be unit tested.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… args
When a preview deployment is built, previewEnv / previewBuildArgs /
previewBuildSecrets are copied onto the application before the build
runs. Add resolution of a ${{preview.prNumber}} token in those three
strings, matching the existing ${{project.*}} / ${{environment.*}}
double-brace convention.
Combined with the ${prNumber} wildcard-domain support, this lets one
service point at another's deterministic preview URL for the same PR,
e.g. VITE_API_URL=https://backend-pr${{preview.prNumber}}.example.com
on a frontend, without knowing the URL in advance.
The substitution is applied in deployPreviewApplication /
rebuildPreviewApplication before prepareEnvironmentVariables runs, rather
than extending that shared resolver, since prepareEnvironmentVariables is
also used by non-preview deployments, compose and databases and does not
know this preview-only token.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this PR about?
Adds a
${prNumber}template variable to the preview deployments Wildcard Domain setting, and a matching${{preview.prNumber}}token for preview env / build args / build secrets.Motivation: when one repo drives two Dokploy applications (e.g. a frontend and a backend), a PR triggers a preview deployment for each — but today's preview domains always contain a random suffix, so neither service can know the other's URL in advance. With this PR, both apps can use deterministic per-PR patterns and cross-reference each other before either is deployed:
frontend-pr${prNumber}.example.combackend-pr${prNumber}.example.comVITE_API_URL=https://backend-pr${{preview.prNumber}}.example.comFRONTEND_URL=https://frontend-pr${{preview.prNumber}}.example.comHow
Two self-contained commits:
${prNumber}in the wildcard domain —generateWildcardDomaininpackages/server/src/services/preview-deployment.tsnow substitutes${prNumber}(from the already-storedpullRequestNumber) before the existing*logic. If no*remains, the domain is returned as-is (fully deterministic); otherwise the legacy*/sslip.io hash path runs unchanged, so*.pr-${prNumber}.example.comcombines per-PR scoping with per-app uniqueness. A domain with neither*nor${prNumber}now throws, since every PR would collide on the same host. The function is renamed togeneratePreviewWildcardDomainand exported for testing — the old name collided with an unrelatedgenerateWildcardDomaininservices/domain.tsthrough the barrel export.${{preview.prNumber}}in preview env — resolved indeployPreviewApplication/rebuildPreviewApplicationover previewEnv, previewBuildArgs and previewBuildSecrets, following the existing${{project.*}}/${{environment.*}}double-brace convention. Kept out of the sharedprepareEnvironmentVariablesresolver on purpose, since that function also serves non-preview deployments, compose and databases.Existing setups are unaffected: with no
${prNumber}in the pattern, behavior is byte-for-byte identical to before (default*.sslip.ioincluded). No schema changes or migrations.Known trade-off
If two applications are given the same
${prNumber}-only pattern, their previews for a given PR would collide on one host — previously impossible because every generated domain embedded the app's own name. The UI tooltip warns about this and recommends per-app prefixes (or*.pr-${prNumber}.…which keeps the app hash). A server-side duplicate-host check increatePreviewDeploymentwould be a good follow-up; happy to add it here if preferred.Relationship to PR #4667
Complementary, not overlapping: #4667's
${{service.<name>.fqdn}}resolves a sibling's applicationId-linked domains, and preview domains are only linked viapreviewDeploymentId— so it resolves production URLs, and structurally can't reach the PR-scoped preview case. This PR covers that case via deterministic domains instead of lookup.Checklist
Before submitting this PR, please make sure that:
canarybranch.Testing done so far: 9 new unit tests for
generatePreviewWildcardDomain(substitution, combined*.pr-${prNumber}form, two-app distinctness, legacy*/sslip.io paths unchanged, both validation throws) — all passing, plus the existing env suite (68/68) and clean typechecks on@dokploy/serverandapps/dokploy. A live end-to-end run via a real GitHub PR webhook is still pending, hence the unchecked box.Issues related (if applicable)
Addresses the cross-service preview URL need described in #2028 (the "alternatives considered" scenario) and #2743, for application-type services. Does not close either: #2028's primary ask is compose preview support, and #2743 asks for per-preview env overrides in the UI.