Initial commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
name: Send campaign
|
||||||
|
on:
|
||||||
|
# Pushing a tag like send/big-announcement is the primary trigger — a
|
||||||
|
# deliberate, git-native, auditable action (git log --tags shows every
|
||||||
|
# real send that ever happened). These are "command tags," not release
|
||||||
|
# tags: fine to delete and re-push if a send needs retrying, since the
|
||||||
|
# actual safety net is listmonk's own draft/paused status check in
|
||||||
|
# `eec-campaigns send`, not tag uniqueness.
|
||||||
|
push:
|
||||||
|
tags: ["send/*"]
|
||||||
|
# workflow_dispatch is kept alongside it for when clicking a button is
|
||||||
|
# more convenient than a local `git tag && git push`. Same command either
|
||||||
|
# way.
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
slug:
|
||||||
|
description: "Campaign slug (campaigns/<slug>/) to send"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
send:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.23.1"
|
||||||
|
|
||||||
|
- name: Install eec-campaigns
|
||||||
|
run: go install gitea.reground.org/will/eec-campaigns@v0.1.4
|
||||||
|
|
||||||
|
- name: Determine campaign slug
|
||||||
|
id: slug
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
echo "value=${{ inputs.slug }}" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "value=${GITHUB_REF#refs/tags/send/}" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Send campaign
|
||||||
|
run: eec-campaigns send "${{ steps.slug.outputs.value }}"
|
||||||
|
env:
|
||||||
|
LISTMONK_BASE_URL: ${{ secrets.CAMPAIGNS_LISTMONK_BASE_URL }}
|
||||||
|
LISTMONK_API_USER: ${{ secrets.CAMPAIGNS_LISTMONK_API_USER }}
|
||||||
|
LISTMONK_API_TOKEN: ${{ secrets.CAMPAIGNS_LISTMONK_API_TOKEN }}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
name: Sync default campaign template
|
||||||
|
on:
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync-template:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.23.1"
|
||||||
|
|
||||||
|
- name: Install eec-campaigns
|
||||||
|
run: go install gitea.reground.org/will/eec-campaigns@v0.1.4
|
||||||
|
|
||||||
|
# TODO: rename "TEMPLATE default" below to "<this-repo-name> default"
|
||||||
|
# (or any name you like) as part of customizing this template.
|
||||||
|
- name: Sync template to listmonk
|
||||||
|
run: eec-campaigns template "TEMPLATE default" email-templates/campaign.html
|
||||||
|
env:
|
||||||
|
LISTMONK_BASE_URL: ${{ secrets.CAMPAIGNS_LISTMONK_BASE_URL }}
|
||||||
|
LISTMONK_API_USER: ${{ secrets.CAMPAIGNS_LISTMONK_API_USER }}
|
||||||
|
LISTMONK_API_TOKEN: ${{ secrets.CAMPAIGNS_LISTMONK_API_TOKEN }}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
name: Sync campaigns
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.23.1"
|
||||||
|
|
||||||
|
- name: Install eec-campaigns
|
||||||
|
run: go install gitea.reground.org/will/eec-campaigns@v0.1.4
|
||||||
|
|
||||||
|
- name: Sync campaigns to listmonk
|
||||||
|
run: eec-campaigns sync .
|
||||||
|
env:
|
||||||
|
LISTMONK_BASE_URL: ${{ secrets.CAMPAIGNS_LISTMONK_BASE_URL }}
|
||||||
|
LISTMONK_API_USER: ${{ secrets.CAMPAIGNS_LISTMONK_API_USER }}
|
||||||
|
LISTMONK_API_TOKEN: ${{ secrets.CAMPAIGNS_LISTMONK_API_TOKEN }}
|
||||||
|
CAMPAIGNS_PREVIEW_EMAIL: ${{ secrets.CAMPAIGNS_PREVIEW_EMAIL }}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
name: Test-send campaign
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
slug:
|
||||||
|
description: "Campaign slug (campaigns/<slug>/) to preview"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
description: "Address to send the preview to"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.23.1"
|
||||||
|
|
||||||
|
- name: Install eec-campaigns
|
||||||
|
run: go install gitea.reground.org/will/eec-campaigns@v0.1.4
|
||||||
|
|
||||||
|
- name: Send preview
|
||||||
|
run: eec-campaigns test "${{ inputs.slug }}" "${{ inputs.email }}"
|
||||||
|
env:
|
||||||
|
LISTMONK_BASE_URL: ${{ secrets.CAMPAIGNS_LISTMONK_BASE_URL }}
|
||||||
|
LISTMONK_API_USER: ${{ secrets.CAMPAIGNS_LISTMONK_API_USER }}
|
||||||
|
LISTMONK_API_TOKEN: ${{ secrets.CAMPAIGNS_LISTMONK_API_TOKEN }}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# campaigns-template
|
||||||
|
|
||||||
|
Gitea template repo for standing up a new domain/client's campaign content repo. Generate a new repo from this one (Gitea → this repo → "Generate Repo," or `POST /api/v1/repos/generate/will/campaigns-template`) rather than cloning it — generating starts the new repo with a clean history of its own.
|
||||||
|
|
||||||
|
Full reference for everything below lives in the [`eec-campaigns` README](https://gitea.reground.org/will/eec-campaigns).
|
||||||
|
|
||||||
|
## After generating a new repo from this template
|
||||||
|
|
||||||
|
1. **Rename the template.** In `.gitea/workflows/sync-template.yml`, replace `TEMPLATE default` with a name specific to this domain (e.g. `<client> default`).
|
||||||
|
2. **Restyle `email-templates/campaign.html`** if this client wants different branding than the stock listmonk template it starts as.
|
||||||
|
3. **Add repo secrets** (Gitea Actions → Secrets): `CAMPAIGNS_LISTMONK_BASE_URL`, `CAMPAIGNS_LISTMONK_API_USER`, `CAMPAIGNS_LISTMONK_API_TOKEN`, and optionally `CAMPAIGNS_PREVIEW_EMAIL` — scoped to this domain's own listmonk instance and its own dedicated API user (see `reground-infrastructure`'s `campaigns` Ansible role for provisioning that user).
|
||||||
|
4. **Check the tool version pin** in all four `.gitea/workflows/*.yml` files (currently `v0.1.0`) — bump it only deliberately, after confirming a newer `eec-campaigns` release works.
|
||||||
|
5. Run the `Sync default campaign template` workflow once.
|
||||||
|
6. Replace this README with a short one for this domain (see `reground-campaigns`'s README for the pattern: a numbered "to send a campaign" list for whoever operates this repo day-to-day).
|
||||||
|
7. Give the client push/PR access to *this repo only* — that's the entire isolation boundary. They never need access to `eec-campaigns`, `campaigns-template`, or any other domain's repo.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
campaigns/
|
||||||
|
<slug>/
|
||||||
|
campaign.md
|
||||||
|
email-templates/
|
||||||
|
campaign.html
|
||||||
|
.gitea/workflows/
|
||||||
|
sync.yml # push to master -> draft + preview
|
||||||
|
send.yml # tag push send/<slug>, or manual dispatch -> real send
|
||||||
|
test.yml # manual dispatch -> re-preview without touching status
|
||||||
|
sync-template.yml # manual dispatch -> push email template as listmonk default
|
||||||
|
```
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
subject: "Welcome!"
|
||||||
|
lists: ["Newsletter"]
|
||||||
|
from_email: "Your Name <hello@example.org>"
|
||||||
|
tags: ["welcome"]
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a sample campaign showing the `campaign.md` format — edit it, rename
|
||||||
|
its directory, or delete it entirely once you've got the hang of things. See
|
||||||
|
the [eec-campaigns README](https://gitea.reground.org/will/eec-campaigns#campaignmd)
|
||||||
|
for the full field reference.
|
||||||
|
|
||||||
|
{{ if .Subscriber.Attribs.first_name }}Hi {{ .Subscriber.Attribs.first_name }},{{ else }}Hi there,{{ end }}
|
||||||
|
|
||||||
|
Thanks for subscribing! You'll hear from us here whenever we've got something
|
||||||
|
worth sharing.
|
||||||
|
|
||||||
|
Talk soon.
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
<!--
|
||||||
|
Listmonk's own stock campaign template (static/email-templates/default.tpl
|
||||||
|
in knadh/listmonk), committed here verbatim as a known-good, unsubscribe-
|
||||||
|
capable starting point rather than something invented from scratch. Synced
|
||||||
|
into listmonk via `campaigns template <name> email-templates/campaign.html`
|
||||||
|
(see internal/campaign/template.go) as the is_default campaign template, so
|
||||||
|
every campaign this tool creates gets a real unsubscribe link/footer without
|
||||||
|
per-campaign template_id wiring. Restyle freely — the two load-bearing tags
|
||||||
|
are `{{ template "content" . }}` (where the campaign body gets injected) and
|
||||||
|
`{{ UnsubscribeURL }}` (the actual unsubscribe link); everything else here is
|
||||||
|
just Listmonk's default look.
|
||||||
|
-->
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ .Campaign.Subject }}</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||||
|
<base target="_blank">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #F0F1F3;
|
||||||
|
font-family: 'Helvetica Neue', 'Segoe UI', Helvetica, sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 26px;
|
||||||
|
margin: 0;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: #f4f4f4f4;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
border-color: #ddd;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrap {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 30px;
|
||||||
|
max-width: 525px;
|
||||||
|
margin: 0 auto;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
background: #0055d4;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-decoration: none !important;
|
||||||
|
color: #fff !important;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px 30px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.button:hover {
|
||||||
|
background: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
.footer a {
|
||||||
|
color: #888;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gutter {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #0055d4;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.wrap {
|
||||||
|
max-width: auto;
|
||||||
|
}
|
||||||
|
.gutter {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="background-color: #F0F1F3;font-family: 'Helvetica Neue', 'Segoe UI', Helvetica, sans-serif;font-size: 15px;line-height: 26px;margin: 0;color: #444;">
|
||||||
|
<div class="gutter" style="padding: 30px;"> </div>
|
||||||
|
<div class="wrap" style="background-color: #fff;padding: 30px;max-width: 525px;margin: 0 auto;border-radius: 5px;">
|
||||||
|
{{ template "content" . }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer" style="text-align: center;font-size: 12px;color: #888;">
|
||||||
|
<p>
|
||||||
|
<a href="{{ UnsubscribeURL }}" style="color: #888;">{{ L.T "email.unsub" }}</a>
|
||||||
|
|
||||||
|
<a href="{{ MessageURL }}" style="color: #888;">{{ L.T "email.viewInBrowser" }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="gutter" style="padding: 30px;"> {{ TrackView }}</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user