Algorithm to generate a preview DNS subdomain from a branch name

Hi, I’m trying to set up an integration to easily fetch a Cloudflare Pages site from its preview URL based on the Git branch name.

Preview deployments · Cloudflare Pages docs mentions that non-alpha-numeric characters are converted to a -, and the name is lowercased. However, it seems like there are a few more details.

Is there a hard-coded max length? If the name ends in a - after getting truncated, would that be chopped off?

For example, I’m starting out with this logic, but want to improve:

branch
  // Non-alphanumeric characters are converted to a -
  .replace(/[^A-Za-z0-9]/g, '-')
  // >1 consecutive - becomes a single -
  .replace(/-{2,}/g, '-')
  .toLowerCase()

I noticed this wasn’t sufficient for a branch name like:

dependabot/npm_and_yarn/dustjs-linkedin-3.0.0, which became https://dependabot-npm-and-yarn-dust.site.pages.dev.

What’s the full logic?

We normalise as you already know, then if it’s over max length (28) we limit. If there’s no usable chars (we normalised to nothing) then we generate a random branch name with the format “branch-{randomChars}”

This is what it looks like in JS (this code isn’t perfect and not optimised, just wrote it now):

const invalidCharsRegex = /[^a-z0-9-]/g;
const maxAliasLength = 28
const alphanum = "abcdefghijklmnopqrstuvwxyz0123456789"

function main() {
	// Simple
	console.log(generateBranchAlias("test-abc"));

	// Lowercase
	console.log(generateBranchAlias("Test-ABC"));

	// Replace special chars
	console.log(generateBranchAlias("Test:abc"));

	// Don't start or end in dash
	console.log(generateBranchAlias("-test-abc-"));

	// Too long
	console.log(generateBranchAlias("abcdef123456abcdef123456abcdef123456"));

	// No usable chars
	console.log(generateBranchAlias("-::::-"));
}

function generateBranchAlias(branch: string) {
	const normalised = trim(branch.toLowerCase().replace(invalidCharsRegex, '-'), '-');

	if (normalised === '') {
		return 'branch-' + randAlphaNum(10);
	}

	if (normalised.length > maxAliasLength) {
		return normalised.substring(0, maxAliasLength);
	}

	return normalised;
}

function trim(str: string, char: string): string {
	while (str.charAt(0) === char) {
		if (str.length === 1) {
			return "";
		}
		str = str.substring(1);
	}

	while (str.charAt(str.length - 1) === char) {
		if (str.length === 1) {
			return "";
		}
		str = str.substring(0, str.length - 1);
	}

	return str;
}

function randAlphaNum(length: number): string {
	let result: string = '';

	for (let i = 0; i < length; i++) {
		result += alphanum[Math.floor(Math.random() * alphanum.length)];
	}

	return result;
}

main();
test-abc
test-abc
test-abc
test-abc
abcdef123456abcdef123456abcd
branch-7b239b05i3
3 Likes

Thank you! Very helpful. That should do the trick.

I also confirmed by testing there are no rules against consecutive dashes (unlike Netlify needs since it uses -- as a delimiter).

For example: test-/--foo--barhello-ther-ok becomes test----foo--barhello-ther-o with Pages.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.