feat(mail): Z-Push Exchange ActiveSync gateway for mobile clients
Wraps Stalwart in EAS so iOS/Android native Mail/Calendar 'Exchange' accounts get two-way mail+calendar+contacts sync (BackendCombined: IMAP + CalDAV /dav/cal/%l/ + CardDAV, credentials pass through). - services/zpush: Z-Push 2.6.4 (AGPLv3, see LICENSE-NOTES.md) on php:8.2-apache-bookworm (trixie dropped libc-client); PHP 8 sysv sprintf fatal sed-patched; autodiscover dispatcher answers mobilesync schema, proxies outlook schema to Stalwart unchanged - prod: zpush Deployment (replicas:1, Recreate — file sync state), /Microsoft-Server-ActiveSync Ingress on mail.dezky.eu (no redirect, POST-heavy), autodiscover.dezky.eu repointed to the dispatcher, selectorless stalwart-imaps/-smtps Services (host-Stalwart is implicit-TLS only: 993/465, no plain 143/587 — verified on node1) - CI: build+deploy zpush like the other apps EAS tops out at 14.1: covers native mobile clients, NOT the Outlook mobile app (needs 16.1) and not new Outlook for Windows (no EAS).
This commit is contained in:
+28
-6
@@ -30,6 +30,7 @@ jobs:
|
||||
operator: ${{ steps.diff.outputs.operator }}
|
||||
website: ${{ steps.diff.outputs.website }}
|
||||
platform_api: ${{ steps.diff.outputs.platform_api }}
|
||||
zpush: ${{ steps.diff.outputs.zpush }}
|
||||
infra: ${{ steps.diff.outputs.infra }}
|
||||
deploy_any: ${{ steps.diff.outputs.deploy_any }}
|
||||
steps:
|
||||
@@ -62,8 +63,9 @@ jobs:
|
||||
hit '^apps/operator/' && out operator true || out operator false
|
||||
hit '^apps/website/' && out website true || out website false
|
||||
hit '^services/platform-api/' && out platform_api true || out platform_api false
|
||||
hit '^services/zpush/' && out zpush true || out zpush false
|
||||
hit '^infrastructure/production/fleet/apps/' && out infra true || out infra false
|
||||
if hit '^apps/(portal|booking|operator)/|^services/platform-api/|^infrastructure/production/fleet/apps/'; then
|
||||
if hit '^apps/(portal|booking|operator)/|^services/(platform-api|zpush)/|^infrastructure/production/fleet/apps/'; then
|
||||
out deploy_any true
|
||||
else
|
||||
out deploy_any false
|
||||
@@ -212,12 +214,28 @@ jobs:
|
||||
docker push "$IMG:latest"
|
||||
docker push "$IMG:${{ github.sha }}"
|
||||
|
||||
# zpush is PHP (Z-Push EAS gateway) — no typecheck/test stage; the docker
|
||||
# build is the only gate.
|
||||
build_zpush:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changes]
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.changes.outputs.zpush == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build + push
|
||||
run: |
|
||||
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.lastcloud.io -u "${{ github.actor }}" --password-stdin
|
||||
IMG=git.lastcloud.io/ronnibaslund/dezky/zpush
|
||||
docker build -t "$IMG:latest" -t "$IMG:${{ github.sha }}" services/zpush
|
||||
docker push "$IMG:latest"
|
||||
docker push "$IMG:${{ github.sha }}"
|
||||
|
||||
# ── Deploy (only what changed) ─────────────────────────────────────────────
|
||||
# always() so skipped builds don't block it; the explicit result checks make
|
||||
# any FAILED build (or its typecheck/test, transitively) abort the deploy.
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changes, build_portal, build_booking, build_operator, build_platform_api]
|
||||
needs: [changes, build_portal, build_booking, build_operator, build_platform_api, build_zpush]
|
||||
if: >-
|
||||
always() &&
|
||||
github.event_name == 'push' && github.ref == 'refs/heads/main' &&
|
||||
@@ -225,7 +243,8 @@ jobs:
|
||||
needs.build_portal.result != 'failure' && needs.build_portal.result != 'cancelled' &&
|
||||
needs.build_booking.result != 'failure' && needs.build_booking.result != 'cancelled' &&
|
||||
needs.build_operator.result != 'failure' && needs.build_operator.result != 'cancelled' &&
|
||||
needs.build_platform_api.result != 'failure' && needs.build_platform_api.result != 'cancelled'
|
||||
needs.build_platform_api.result != 'failure' && needs.build_platform_api.result != 'cancelled' &&
|
||||
needs.build_zpush.result != 'failure' && needs.build_zpush.result != 'cancelled'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -246,6 +265,7 @@ jobs:
|
||||
BUILT_BOOKING: ${{ needs.build_booking.result }}
|
||||
BUILT_OPERATOR: ${{ needs.build_operator.result }}
|
||||
BUILT_PLATFORM_API: ${{ needs.build_platform_api.result }}
|
||||
BUILT_ZPUSH: ${{ needs.build_zpush.result }}
|
||||
run: |
|
||||
export KUBECONFIG=/tmp/kubeconfig
|
||||
echo "$KUBECONFIG_B64" | base64 -d > "$KUBECONFIG"
|
||||
@@ -256,12 +276,14 @@ jobs:
|
||||
[booking]=${{ needs.changes.outputs.booking }}
|
||||
[operator]=${{ needs.changes.outputs.operator }}
|
||||
[platform-api]=${{ needs.changes.outputs.platform_api }}
|
||||
[zpush]=${{ needs.changes.outputs.zpush }}
|
||||
)
|
||||
declare -A BUILT=(
|
||||
[portal]=$BUILT_PORTAL
|
||||
[booking]=$BUILT_BOOKING
|
||||
[operator]=$BUILT_OPERATOR
|
||||
[platform-api]=$BUILT_PLATFORM_API
|
||||
[zpush]=$BUILT_ZPUSH
|
||||
)
|
||||
# Deployable = changed AND its image was actually built this run.
|
||||
deployable() { [ "${CHANGED[$1]}" = "true" ] && [ "${BUILT[$1]}" = "success" ]; }
|
||||
@@ -271,7 +293,7 @@ jobs:
|
||||
# app to its CURRENT live image (or this push's sha if it was
|
||||
# rebuilt) so the apply never resets anything to :latest.
|
||||
cd infrastructure/production/fleet/apps
|
||||
for app in portal booking platform-api operator; do
|
||||
for app in portal booking platform-api operator zpush; do
|
||||
if deployable "$app"; then
|
||||
IMG="$REG/$app:$SHA"
|
||||
else
|
||||
@@ -280,10 +302,10 @@ jobs:
|
||||
kustomize edit set image "$REG/$app=$IMG"
|
||||
done
|
||||
kubectl apply -k .
|
||||
ROLL="portal booking platform-api operator"
|
||||
ROLL="portal booking platform-api operator zpush"
|
||||
else
|
||||
# App-only change: roll just the changed apps; nothing else moves.
|
||||
for app in portal booking platform-api operator; do
|
||||
for app in portal booking platform-api operator zpush; do
|
||||
if deployable "$app"; then
|
||||
kubectl -n dezky-apps set image "deploy/$app" "$app=$REG/$app:$SHA"
|
||||
ROLL="$ROLL $app"
|
||||
|
||||
Reference in New Issue
Block a user