Check / check (pull_request) Skipped
App names may now contain dots, such as sneak.berlin: runs of lowercase letters and numbers joined by single dots or by hyphens, 2 to 63 characters. Docker accepts every such name in the app's image name, upaas-<name>; a dot needs a letter or number on both sides because Docker requires it. The rule also keeps a dot off either end, so the name is safe as a directory and log file name. The new and edit app forms use the same pattern. Their old one was not a valid regular expression under the flag browsers compile it with, so browsers ignored it. A test creates an app named sneak.berlin through the new app form, then builds and deploys it against the fake Docker API and checks the image and container names with Docker's own rules. Model: opus-5-5
130 lines
4.6 KiB
HTML
130 lines
4.6 KiB
HTML
{{template "base" .}}
|
|
|
|
{{define "title"}}New App - µPaaS{{end}}
|
|
|
|
{{define "content"}}
|
|
{{template "nav" .}}
|
|
|
|
<main class="max-w-2xl mx-auto px-4 py-8">
|
|
<div class="mb-6">
|
|
<a href="/" class="text-primary-600 hover:text-primary-800 inline-flex items-center">
|
|
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
|
|
</svg>
|
|
Back to Dashboard
|
|
</a>
|
|
</div>
|
|
|
|
<h1 class="text-2xl font-medium text-gray-900 mb-6">Create New Application</h1>
|
|
|
|
<div class="card p-6">
|
|
{{template "alert-error" .}}
|
|
|
|
<form method="POST" action="/apps" class="space-y-6">
|
|
{{ .CSRFField }}
|
|
<div class="form-group">
|
|
<label for="name" class="label">App Name</label>
|
|
<input
|
|
type="text"
|
|
id="name"
|
|
name="name"
|
|
value="{{.Name}}"
|
|
required
|
|
minlength="2"
|
|
maxlength="63"
|
|
pattern="[a-z0-9]+((\.|-+)[a-z0-9]+)*"
|
|
class="input"
|
|
placeholder="my-app"
|
|
>
|
|
<p class="text-sm text-gray-500 mt-1">Lowercase letters, numbers, hyphens, and dots, such as my-app or example.com</p>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="repo_url" class="label">Repository URL (SSH)</label>
|
|
<input
|
|
type="text"
|
|
id="repo_url"
|
|
name="repo_url"
|
|
value="{{.RepoURL}}"
|
|
required
|
|
class="input font-mono"
|
|
placeholder="git@gitea.example.com:user/repo.git"
|
|
>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="form-group">
|
|
<label for="branch" class="label">Branch</label>
|
|
<input
|
|
type="text"
|
|
id="branch"
|
|
name="branch"
|
|
value="{{if .Branch}}{{.Branch}}{{else}}main{{end}}"
|
|
class="input"
|
|
placeholder="main"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="dockerfile_path" class="label">Dockerfile Path</label>
|
|
<input
|
|
type="text"
|
|
id="dockerfile_path"
|
|
name="dockerfile_path"
|
|
value="{{if .DockerfilePath}}{{.DockerfilePath}}{{else}}Dockerfile{{end}}"
|
|
class="input"
|
|
placeholder="Dockerfile"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="border-gray-200">
|
|
|
|
<h3 class="text-lg font-medium text-gray-900">Optional Settings</h3>
|
|
|
|
<div class="form-group">
|
|
<label for="docker_network" class="label">Docker Network</label>
|
|
<input
|
|
type="text"
|
|
id="docker_network"
|
|
name="docker_network"
|
|
value="{{.DockerNetwork}}"
|
|
class="input"
|
|
placeholder="bridge"
|
|
>
|
|
<p class="text-sm text-gray-500 mt-1">Leave empty to use default bridge network</p>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="ntfy_topic" class="label">Ntfy Topic URL</label>
|
|
<input
|
|
type="url"
|
|
id="ntfy_topic"
|
|
name="ntfy_topic"
|
|
value="{{.NtfyTopic}}"
|
|
class="input"
|
|
placeholder="https://ntfy.sh/my-topic"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="slack_webhook" class="label">Slack Webhook URL</label>
|
|
<input
|
|
type="url"
|
|
id="slack_webhook"
|
|
name="slack_webhook"
|
|
value="{{.SlackWebhook}}"
|
|
class="input"
|
|
placeholder="https://hooks.slack.com/services/..."
|
|
>
|
|
</div>
|
|
|
|
<div class="flex justify-end gap-3 pt-4">
|
|
<a href="/" class="btn-secondary">Cancel</a>
|
|
<button type="submit" class="btn-primary">Create App</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</main>
|
|
{{end}}
|