Update to Sieve Deployment Workflow
In the previous post on deploying Sieve filters to Stalwart using JMAP the workflow always created a new script. After some testing I realised it should update the existing script when one already exists. Below is the corrected workflow.
1name: Deploy to Stalwart
2"on":
3 push:
4 paths:
5 - 'stalwart.sieve'
6 branches:
7 - main
8 workflow_dispatch:
9
10jobs:
11 deploy:
12 runs-on: ubuntu-latest
13 steps:
14 - uses: actions/checkout@v3
15 - name: Install tools
16 run: |
17 sudo apt-get update
18 sudo apt-get install -y jq
19 - name: Upload via JMAP
20 env:
21 STALWART_JMAP_URL: ${{ vars.STALWART_JMAP_URL }}
22 STALWART_USER: ${{ secrets.STALWART_USER }}
23 STALWART_PASS: ${{ secrets.STALWART_PASS }}
24 run: |
25 set -e
26 set -x
27 base_url="${STALWART_JMAP_URL%/jmap*}"
28 session_json=$(curl -X GET -k -u "$STALWART_USER:$STALWART_PASS" "$base_url/.well-known/jmap")
29 account_id=$(echo "$session_json" | jq -r '.primaryAccounts["urn:ietf:params:jmap:sieve"]')
30
31 jmap_endpoint="${STALWART_JMAP_URL%/}"
32 upload_url="${jmap_endpoint}/upload/${account_id}"
33
34 curl -X POST -k -u "$STALWART_USER:$STALWART_PASS" \
35 -H "Content-Type: application/sieve" \
36 --data-binary @stalwart.sieve "$upload_url" > upload.json
37 blob_id=$(jq -r '.blobId' upload.json)
38 if [ "$blob_id" = "null" ] || [ -z "$blob_id" ]; then
39 echo "Upload failed" >&2
40 cat upload.json
41 exit 1
42 fi
43
44 list_body=$(jq -n --arg accountId "$account_id" '{
45 "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:sieve"],
46 "methodCalls": [["SieveScript/get", {"accountId": $accountId}, "0"]]
47 }')
48 list_resp=$(curl -X POST -k -u "$STALWART_USER:$STALWART_PASS" \
49 -H "Content-Type: application/json" \
50 -d "$list_body" "$jmap_endpoint")
51 echo "$list_resp" | jq
52 existing_id=$(echo "$list_resp" | jq -r '.methodResponses[0][1].list[] | select(.name=="stalwart.sieve") | .id')
53
54 if [ -n "$existing_id" ] && [ "$existing_id" != "null" ]; then
55 set_body=$(jq -n --arg accountId "$account_id" --arg blob "$blob_id" --arg id "$existing_id" '{
56 "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:sieve"],
57 "methodCalls": [["SieveScript/set", {
58 "accountId": $accountId,
59 "update": {($id): {"blobId": $blob}},
60 "onSuccessActivateScript": $id
61 }, "0"]]
62 }')
63 else
64 set_body=$(jq -n --arg accountId "$account_id" --arg blob "$blob_id" '{
65 "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:sieve"],
66 "methodCalls": [["SieveScript/set", {
67 "accountId": $accountId,
68 "create": {"A": {"name": "stalwart.sieve", "blobId": $blob}},
69 "onSuccessActivateScript": "#A"
70 }, "0"]]
71 }')
72 fi
73 curl -X POST -k -u "$STALWART_USER:$STALWART_PASS" \
74 -H "Content-Type: application/json" \
75 -d "$set_body" "$jmap_endpoint" | jq
This version first queries existing scripts and either updates the current one or creates it if missing.
This post was written with the assistance of an AI tool.