-
Notifications
You must be signed in to change notification settings - Fork 12
feat: add staged deployment update notifier #272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| [Unit] | ||
| Description=Check for staged Aurora deployments | ||
| Documentation=https://docs.getaurora.dev/ | ||
| After=uupd.service rpm-ostreed.service | ||
|
|
||
| [Service] | ||
| Type=oneshot | ||
| ExecStart=/usr/libexec/aurora-deployment-check |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| [Unit] | ||
| Description=Periodically check for staged Aurora deployments | ||
|
|
||
| [Timer] | ||
| OnBootSec=5min | ||
| OnUnitActiveSec=1h | ||
| AccuracySec=5min | ||
| Persistent=false | ||
| Unit=aurora-deployment-check.service | ||
|
|
||
| [Install] | ||
| WantedBy=timers.target |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| [Unit] | ||
| OnSuccess=aurora-deployment-check.service |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| [Unit] | ||
| Description=Watch for staged Aurora deployment status | ||
| Documentation=https://docs.getaurora.dev/ | ||
|
|
||
| [Path] | ||
| PathExists=/run/aurora/staged-ready | ||
| Unit=aurora-deployment-notifier.service | ||
|
|
||
| [Install] | ||
| WantedBy=default.target |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| [Unit] | ||
| Description=Notify when an Aurora deployment is ready to boot | ||
| Documentation=https://docs.getaurora.dev/ | ||
|
|
||
| [Service] | ||
| Type=oneshot | ||
| RemainAfterExit=yes | ||
| ExecStart=/usr/libexec/aurora-deployment-notifier | ||
|
|
||
| [Install] | ||
| WantedBy=default.target |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| d /run/aurora 0755 root root - |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| STATUS_DIR="${AURORA_DEPLOYMENT_STATUS_DIR:-/run/aurora}" | ||
| FLAG_FILE="${STATUS_DIR}/staged-ready" | ||
| STATUS_FILE="${STATUS_DIR}/deployment-status.json" | ||
|
|
||
| SOURCE="" | ||
| STAGED_ID="" | ||
| BOOTED_ID="" | ||
|
|
||
| write_status() { | ||
| local tmpfile | ||
| tmpfile="$(mktemp "${STATUS_DIR}/deployment-status.XXXXXX")" | ||
|
|
||
| jq -n \ | ||
| --arg source "${SOURCE}" \ | ||
| --arg staged_id "${STAGED_ID}" \ | ||
| --arg booted_id "${BOOTED_ID}" \ | ||
| --arg created_at "$(date --iso-8601=seconds)" \ | ||
| '{ | ||
| ready: true, | ||
| source: $source, | ||
| staged_id: $staged_id, | ||
| booted_id: $booted_id, | ||
| created_at: $created_at | ||
| }' > "${tmpfile}" | ||
|
|
||
| chmod 0644 "${tmpfile}" | ||
| mv -f "${tmpfile}" "${STATUS_FILE}" | ||
| printf 'ready\n' > "${FLAG_FILE}" | ||
| chmod 0644 "${FLAG_FILE}" | ||
| } | ||
|
|
||
| clear_status() { | ||
| rm -f "${FLAG_FILE}" "${STATUS_FILE}" | ||
| } | ||
|
|
||
| check_bootc() { | ||
| local bootc_json | ||
| local staged_id | ||
| local booted_id | ||
|
|
||
| command -v bootc >/dev/null 2>&1 || return 1 | ||
| bootc_json="$(bootc status --json 2>/dev/null)" || return 1 | ||
|
|
||
| staged_id="$(jq -er ' | ||
| .status as $status | ||
| | select($status.staged != null and $status.staged != {}) | ||
| | ( | ||
| $status.staged.image.imageDigest | ||
| // $status.staged.image.digest | ||
| // $status.staged.ostree.checksum | ||
| // $status.staged.checksum | ||
| // ($status.staged | tostring) | ||
| ) | ||
| ' <<< "${bootc_json}" 2>/dev/null)" || return 1 | ||
|
|
||
| booted_id="$(jq -r ' | ||
| .status.booted.image.imageDigest | ||
| // .status.booted.image.digest | ||
| // .status.booted.ostree.checksum | ||
| // .status.booted.checksum | ||
| // empty | ||
| ' <<< "${bootc_json}" 2>/dev/null)" | ||
|
|
||
| if [[ -n "${staged_id}" && "${staged_id}" != "${booted_id}" ]]; then | ||
| SOURCE="bootc" | ||
| STAGED_ID="${staged_id}" | ||
| BOOTED_ID="${booted_id}" | ||
| return 0 | ||
| fi | ||
|
|
||
| return 1 | ||
| } | ||
|
|
||
| check_rpm_ostree() { | ||
| local ostree_json | ||
| local staged_json | ||
| local staged_id | ||
| local booted_id | ||
|
|
||
| command -v rpm-ostree >/dev/null 2>&1 || return 1 | ||
| ostree_json="$(rpm-ostree status --json 2>/dev/null)" || return 1 | ||
|
|
||
| staged_json="$(jq -ec '[.deployments[]? | select(.staged == true)] | first // empty' <<< "${ostree_json}" 2>/dev/null)" || return 1 | ||
| [[ -n "${staged_json}" ]] || return 1 | ||
|
|
||
| staged_id="$(jq -r '.checksum // .version // .origin // tostring' <<< "${staged_json}" 2>/dev/null)" | ||
| booted_id="$(jq -r '[.deployments[]? | select(.booted == true)] | first | .checksum // .version // .origin // empty' <<< "${ostree_json}" 2>/dev/null)" | ||
|
|
||
| if [[ -n "${staged_id}" && "${staged_id}" != "${booted_id}" ]]; then | ||
| SOURCE="rpm-ostree" | ||
| STAGED_ID="${staged_id}" | ||
| BOOTED_ID="${booted_id}" | ||
| return 0 | ||
| fi | ||
|
|
||
| return 1 | ||
| } | ||
|
|
||
| main() { | ||
| install -d -m 0755 -o root -g root "${STATUS_DIR}" | ||
|
|
||
| if check_bootc || check_rpm_ostree; then | ||
| write_status | ||
| else | ||
| clear_status | ||
| fi | ||
| } | ||
|
|
||
| main "$@" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| STATUS_DIR="${AURORA_DEPLOYMENT_STATUS_DIR:-/run/aurora}" | ||
| FLAG_FILE="${STATUS_DIR}/staged-ready" | ||
| STATUS_FILE="${STATUS_DIR}/deployment-status.json" | ||
| STATE_DIR="${XDG_STATE_HOME:-${HOME}/.local/state}/aurora/deployment-notifier" | ||
| LAST_NOTIFIED_FILE="${STATE_DIR}/last-notified" | ||
|
|
||
| [[ -f "${FLAG_FILE}" ]] || exit 0 | ||
| command -v notify-send >/dev/null 2>&1 || exit 0 | ||
|
|
||
| staged_id="" | ||
| if [[ -f "${STATUS_FILE}" ]] && command -v jq >/dev/null 2>&1; then | ||
| staged_id="$(jq -r '.staged_id // empty' "${STATUS_FILE}" 2>/dev/null || true)" | ||
| fi | ||
|
|
||
| if [[ -z "${staged_id}" ]]; then | ||
| staged_id="$(sha256sum "${FLAG_FILE}" | cut -d ' ' -f 1)" | ||
| fi | ||
|
|
||
| mkdir -p "${STATE_DIR}" | ||
|
|
||
| if [[ -f "${LAST_NOTIFIED_FILE}" ]] && [[ "$(<"${LAST_NOTIFIED_FILE}")" == "${staged_id}" ]]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| notify-send \ | ||
| --app-name="Aurora" \ | ||
| --icon="system-software-update" \ | ||
| --urgency=normal \ | ||
| "System update ready" \ | ||
| "Restart your device to finish applying the staged Aurora update." | ||
|
|
||
| printf '%s\n' "${staged_id}" > "${LAST_NOTIFIED_FILE}" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # Toggle Aurora staged deployment desktop notifications. | ||
| [group('Aurora')] | ||
| aurora-update-notifier action="status": | ||
|
arpit1385 marked this conversation as resolved.
|
||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| action="{{ action }}" | ||
| system_timer="aurora-deployment-check.timer" | ||
| system_service="aurora-deployment-check.service" | ||
| user_path="aurora-deployment-notifier.path" | ||
|
|
||
| case "${action}" in | ||
| enable|on) | ||
| systemctl --user enable --now "${user_path}" | ||
| sudo systemctl enable --now "${system_timer}" | ||
| sudo systemctl start "${system_service}" || true | ||
| echo "Aurora update notifications enabled." | ||
| ;; | ||
| disable|off) | ||
| systemctl --user disable --now "${user_path}" || true | ||
| sudo systemctl disable --now "${system_timer}" || true | ||
| rm -f "${XDG_STATE_HOME:-${HOME}/.local/state}/aurora/deployment-notifier/last-notified" | ||
| echo "Aurora update notifications disabled." | ||
| ;; | ||
| status) | ||
| echo "User notifier:" | ||
| systemctl --user --no-pager status "${user_path}" || true | ||
| echo | ||
| echo "System checker:" | ||
| systemctl --no-pager status "${system_timer}" || true | ||
| ;; | ||
| *) | ||
| echo "Usage: ujust aurora-update-notifier [enable|disable|status]" | ||
| exit 2 | ||
| ;; | ||
|
Comment on lines
+12
to
+35
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We usually have one recipe entrypoint and then use gum to select actions like in this case disable|status and so on. I think this would be nice here as well.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will try implementing the entrypoint and selection via gum. |
||
| esac | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if we could get rid of this duplication with the user and system service units.
I think we might be able to use this neat systemd feature for that
man systemd.unit(5)
See for an example
systemd-zram-setup@.service systemd-zram-setup@zram0.serviceThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try testing and implementing it this way.