mirror of
https://github.com/chatmail/relay.git
synced 2026-05-10 07:54:36 +00:00
feat: add CI for docker
Docker and Compose support is provided through a standalone repo at https://github.com/chatmail/docker, add reusable Docker build/test CI jobs to staging workflows and a Docker docs stub pointing to the chatmail/docker repository. Requires CHATMAIL_DOCKER_DISPATCH_TOKEN secret in relay repo settings (fine-grained PAT with contents:write on chatmail/docker).
This commit is contained in:
125
.github/workflows/docker-deploy.yaml
vendored
Normal file
125
.github/workflows/docker-deploy.yaml
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
name: Docker deploy
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
staging_host:
|
||||
required: true
|
||||
type: string
|
||||
description: 'SSH hostname (e.g. staging2.testrun.org)'
|
||||
mail_domain:
|
||||
required: true
|
||||
type: string
|
||||
description: 'MAIL_DOMAIN for docker compose'
|
||||
zone_file:
|
||||
required: true
|
||||
type: string
|
||||
description: 'Default zone file basename (e.g. staging.testrun.org-default.zone)'
|
||||
|
||||
jobs:
|
||||
deploy-docker:
|
||||
name: Docker deploy on ${{ inputs.staging_host }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
environment:
|
||||
name: ${{ inputs.staging_host }}
|
||||
url: https://${{ inputs.staging_host }}/
|
||||
concurrency: ${{ inputs.staging_host }}
|
||||
env:
|
||||
VPS: root@${{ inputs.staging_host }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir ~/.ssh
|
||||
echo "${{ secrets.STAGING_SSH_KEY }}" >> ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan ${{ inputs.staging_host }} > ~/.ssh/known_hosts
|
||||
# Reuse TCP connection for all subsequent ssh/scp calls
|
||||
echo -e "Host ${{ inputs.staging_host }}\n ControlMaster auto\n ControlPath ~/.ssh/ctrl-%r@%h:%p\n ControlPersist 10m" >> ~/.ssh/config
|
||||
|
||||
- name: stop bare services, install Docker, prepare mounts
|
||||
run: |
|
||||
ssh $VPS bash -s <<'EOF'
|
||||
systemctl stop postfix dovecot nginx opendkim unbound filtermail doveauth chatmail-metadata iroh-relay mtail fcgiwrap acmetool 2>/dev/null || true
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && chmod a+r /etc/apt/keyrings/docker.asc
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list
|
||||
apt-get update
|
||||
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
mkdir -p /srv/chatmail/certs /srv/chatmail/dkim
|
||||
cp -a /var/lib/acme/. /srv/chatmail/certs/ || true
|
||||
cp -a /etc/dkimkeys/. /srv/chatmail/dkim/ || true
|
||||
cp /etc/chatmail/chatmail.ini /srv/chatmail/chatmail.ini
|
||||
EOF
|
||||
|
||||
- name: deploy with Docker
|
||||
run: |
|
||||
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
|
||||
GHCR_IMAGE="ghcr.io/chatmail/docker:sha-${SHORT_SHA}"
|
||||
rsync -avz --exclude='.git' --exclude='venv' --exclude='__pycache__' ./ $VPS:/srv/chatmail/relay/
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | ssh $VPS "docker login ghcr.io -u ${{ github.actor }} --password-stdin && \
|
||||
docker pull ${GHCR_IMAGE} && \
|
||||
cd /srv/chatmail/relay && CHATMAIL_IMAGE=${GHCR_IMAGE} MAIL_DOMAIN=${{ inputs.mail_domain }} docker compose -f docker/docker-compose.yaml -f docker/docker-compose.ci.yaml up -d"
|
||||
|
||||
- name: wait for container healthy
|
||||
run: |
|
||||
ssh $VPS 'docker exec chatmail journalctl -f --no-pager' &
|
||||
LOG_PID=$!
|
||||
trap "kill $LOG_PID 2>/dev/null || true" EXIT
|
||||
for i in $(seq 1 60); do
|
||||
status=$(ssh $VPS 'docker inspect --format={{.State.Health.Status}} chatmail 2>/dev/null' || echo "missing")
|
||||
echo " [$i/60] status=$status"
|
||||
if [ "$status" = "healthy" ]; then
|
||||
echo "Container is healthy."
|
||||
exit 0
|
||||
fi
|
||||
if [ "$status" = "unhealthy" ]; then
|
||||
echo "Container is unhealthy!"
|
||||
break
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
echo "Container did not become healthy."
|
||||
kill $LOG_PID 2>/dev/null || true
|
||||
ssh $VPS bash -s <<'EOF'
|
||||
echo "--- failed units ---"
|
||||
docker exec chatmail systemctl --failed --no-pager || true
|
||||
echo "--- service logs ---"
|
||||
docker exec chatmail journalctl -u dovecot -u postfix -u nginx -u unbound --no-pager -n 50 || true
|
||||
echo "--- listening ports ---"
|
||||
docker exec chatmail ss -tlnp || true
|
||||
echo "--- chatmail.ini ---"
|
||||
docker exec chatmail cat /etc/chatmail/chatmail.ini || true
|
||||
EOF
|
||||
exit 1
|
||||
|
||||
- name: show container state
|
||||
run: |
|
||||
ssh $VPS bash -s <<'EOF'
|
||||
echo "--- listening ports ---"
|
||||
docker exec chatmail ss -tlnp
|
||||
echo "--- chatmail.ini ---"
|
||||
docker exec chatmail cat /etc/chatmail/chatmail.ini
|
||||
EOF
|
||||
|
||||
- name: Docker integration tests
|
||||
run: ssh $VPS 'docker exec chatmail cmdeploy test --slow --ssh-host @local'
|
||||
|
||||
- name: Docker DNS
|
||||
run: |
|
||||
git checkout .github/workflows/${{ inputs.zone_file }}
|
||||
ssh $VPS bash -s <<'EOF'
|
||||
docker exec chatmail chown opendkim:opendkim -R /etc/dkimkeys
|
||||
docker exec chatmail cmdeploy dns --ssh-host @local --zonefile /opt/chatmail/staging.zone --verbose
|
||||
docker cp chatmail:/opt/chatmail/staging.zone /tmp/staging.zone
|
||||
EOF
|
||||
scp $VPS:/tmp/staging.zone staging-generated.zone
|
||||
cat staging-generated.zone >> .github/workflows/${{ inputs.zone_file }}
|
||||
cat .github/workflows/${{ inputs.zone_file }}
|
||||
scp .github/workflows/${{ inputs.zone_file }} root@ns.testrun.org:/etc/nsd/${{ inputs.staging_host }}.zone
|
||||
ssh root@ns.testrun.org "nsd-checkzone ${{ inputs.staging_host }} /etc/nsd/${{ inputs.staging_host }}.zone && systemctl reload nsd"
|
||||
|
||||
- name: Docker final DNS check
|
||||
run: ssh $VPS 'docker exec chatmail cmdeploy dns -v --ssh-host @local'
|
||||
19
.github/workflows/test-and-deploy-ipv4only.yaml
vendored
19
.github/workflows/test-and-deploy-ipv4only.yaml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- j4n/docker-pr
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'scripts/**'
|
||||
@@ -12,6 +13,11 @@ on:
|
||||
- 'LICENSE'
|
||||
|
||||
jobs:
|
||||
trigger-docker-build:
|
||||
if: github.event_name == 'push'
|
||||
uses: ./.github/workflows/trigger-docker-build.yaml
|
||||
secrets: inherit
|
||||
|
||||
deploy:
|
||||
name: deploy on staging-ipv4.testrun.org, and run tests
|
||||
runs-on: ubuntu-latest
|
||||
@@ -22,6 +28,8 @@ jobs:
|
||||
concurrency: staging-ipv4.testrun.org
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: prepare SSH
|
||||
run: |
|
||||
@@ -63,7 +71,7 @@ jobs:
|
||||
# download acme & dkim state from ns.testrun.org
|
||||
rsync -e "ssh -o StrictHostKeyChecking=accept-new" -avz root@ns.testrun.org:/tmp/acme-ipv4/acme acme-restore || true
|
||||
rsync -avz root@ns.testrun.org:/tmp/dkimkeys-ipv4/dkimkeys dkimkeys-restore || true
|
||||
# restore acme & dkim state to staging2.testrun.org
|
||||
# restore acme & dkim state to staging-ipv4.testrun.org
|
||||
rsync -avz acme-restore/acme root@staging-ipv4.testrun.org:/var/lib/ || true
|
||||
rsync -avz dkimkeys-restore/dkimkeys root@staging-ipv4.testrun.org:/etc/ || true
|
||||
ssh -o StrictHostKeyChecking=accept-new -v root@staging-ipv4.testrun.org chown root:root -R /var/lib/acme || true
|
||||
@@ -102,3 +110,12 @@ jobs:
|
||||
- name: cmdeploy dns
|
||||
run: ssh root@staging-ipv4.testrun.org "cd relay && scripts/cmdeploy dns -v --ssh-host localhost"
|
||||
|
||||
deploy-docker:
|
||||
needs: [deploy, trigger-docker-build]
|
||||
if: github.event_name == 'push'
|
||||
uses: ./.github/workflows/docker-deploy.yaml
|
||||
with:
|
||||
staging_host: staging-ipv4.testrun.org
|
||||
mail_domain: staging-ipv4.testrun.org
|
||||
zone_file: staging-ipv4.testrun.org-default.zone
|
||||
secrets: inherit
|
||||
|
||||
15
.github/workflows/test-and-deploy.yaml
vendored
15
.github/workflows/test-and-deploy.yaml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- j4n/docker-pr
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'scripts/**'
|
||||
@@ -12,6 +13,11 @@ on:
|
||||
- 'LICENSE'
|
||||
|
||||
jobs:
|
||||
trigger-docker-build:
|
||||
if: github.event_name == 'push'
|
||||
uses: ./.github/workflows/trigger-docker-build.yaml
|
||||
secrets: inherit
|
||||
|
||||
deploy:
|
||||
name: deploy on staging2.testrun.org, and run tests
|
||||
runs-on: ubuntu-latest
|
||||
@@ -95,3 +101,12 @@ jobs:
|
||||
- name: cmdeploy dns
|
||||
run: cmdeploy dns -v
|
||||
|
||||
deploy-docker:
|
||||
needs: [deploy, trigger-docker-build]
|
||||
if: github.event_name == 'push'
|
||||
uses: ./.github/workflows/docker-deploy.yaml
|
||||
with:
|
||||
staging_host: staging2.testrun.org
|
||||
mail_domain: staging2.testrun.org
|
||||
zone_file: staging.testrun.org-default.zone
|
||||
secrets: inherit
|
||||
|
||||
24
.github/workflows/trigger-docker-build.yaml
vendored
Normal file
24
.github/workflows/trigger-docker-build.yaml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Trigger Docker image build
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
trigger-docker-build:
|
||||
name: Trigger Docker image build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.CHATMAIL_DOCKER_DISPATCH_TOKEN }}
|
||||
script: |
|
||||
await github.rest.repos.createDispatchEvent({
|
||||
owner: 'chatmail',
|
||||
repo: 'docker',
|
||||
event_type: 'relay-updated',
|
||||
client_payload: {
|
||||
relay_ref: context.ref,
|
||||
relay_sha: context.sha,
|
||||
relay_sha_short: context.sha.slice(0, 7)
|
||||
}
|
||||
})
|
||||
@@ -98,6 +98,13 @@ steps. Please substitute it with your own domain.
|
||||
configure at your DNS provider (it can take some time until they are
|
||||
public).
|
||||
|
||||
Docker installation
|
||||
-------------------
|
||||
|
||||
There is experimental support for running chatmail via Docker Compose.
|
||||
See the `chatmail/docker README <https://github.com/chatmail/docker>`_
|
||||
for full setup instructions.
|
||||
|
||||
Other helpful commands
|
||||
----------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user