From f79b1537c944ab46da99ceb9a86af7b6374a260f Mon Sep 17 00:00:00 2001 From: root Date: Wed, 3 Dec 2025 12:28:44 +0000 Subject: [PATCH 1/5] fix(place/booking notifier): allow metadata_changed action --- .gitignore | 2 ++ drivers/place/booking_notifier.cr | 33 +++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 4313fa25e98..b446a0cff04 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ lib .logs repositories/* src +docker-compose.yml +harness diff --git a/drivers/place/booking_notifier.cr b/drivers/place/booking_notifier.cr index ba301dad770..85aa4f9b445 100644 --- a/drivers/place/booking_notifier.cr +++ b/drivers/place/booking_notifier.cr @@ -192,18 +192,30 @@ class Place::BookingNotifier < PlaceOS::Driver booking_details = Booking.from_json payload # Only process booking types of interest - return unless booking_details.booking_type == @booking_type + unless booking_details.booking_type == @booking_type + logger.debug { "ignoring booking #{booking_details.id}: type '#{booking_details.booking_type}' != '#{@booking_type}'" } + return + end # Ignore when a bookings state is updated - return unless {"approved", "cancelled"}.includes?(booking_details.action) + unless {"approved", "cancelled", "metadata_changed"}.includes?(booking_details.action) + logger.debug { "ignoring booking #{booking_details.id}: action '#{booking_details.action}' not in allowed list" } + return + end # Ignore the same event in a short period of time previous = @debounce[booking_details.id]? - return if previous && previous[0] == booking_details.action + if previous && previous[0] == booking_details.action + logger.debug { "ignoring booking #{booking_details.id}: debounced action '#{booking_details.action}'" } + return + end @debounce[booking_details.id] = {booking_details.action, Time.utc.to_unix} building_zone, notify_details, attachments = get_building_name(booking_details.zones) - return unless notify_details && building_zone && attachments + unless notify_details && building_zone && attachments + logger.debug { "ignoring booking #{booking_details.id}: no notify details found for zones #{booking_details.zones}" } + return + end building_key = notify_details.name.downcase.gsub(' ', '_') @@ -216,7 +228,10 @@ class Place::BookingNotifier < PlaceOS::Driver ending = Time.unix(booking_details.booking_end).in(location) # Ignore changes to meetings that have already ended - return if Time.utc > ending + if Time.utc > ending + logger.debug { "ignoring booking #{booking_details.id}: booking has already ended" } + return + end attach = attachments.first? @@ -281,19 +296,25 @@ class Place::BookingNotifier < PlaceOS::Driver end if booking_details.action == "approved" + logger.debug { "sending approved notification for booking #{booking_details.id}" } mailer.send_template( to: send_to, template: {"bookings", third_party ? "booked_by_notify#{@template_suffix}" : "booking_notify#{@template_suffix}"}, args: args, attachments: attachments ) - else + elsif booking_details.action == "cancelled" || (booking_details.action == "metadata_changed" && booking_details.extension_data.dig?("details", "status").try(&.as_s) == "cancelled") + logger.debug { "sending cancelled notification for booking #{booking_details.id} (action: #{booking_details.action})" } mailer.send_template( to: send_to, template: {"bookings", "cancelled#{@template_suffix}"}, args: args, attachments: attachments ) + else + # metadata_changed but not a cancellation - skip notification + logger.debug { "ignoring booking #{booking_details.id}: metadata_changed action but status is '#{booking_details.extension_data.dig?("details", "status")}' (not cancelled)" } + return end staff_api.booking_state(booking_details.id, "notified", booking_details.instance).get From 4f4f192e50192836106a992b0938ccec36a524fa Mon Sep 17 00:00:00 2001 From: root Date: Wed, 3 Dec 2025 12:38:42 +0000 Subject: [PATCH 2/5] fix(place/booking notifier): allow metadata_changed action for approvals --- drivers/place/booking_notifier.cr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/place/booking_notifier.cr b/drivers/place/booking_notifier.cr index 85aa4f9b445..dc560c2c22c 100644 --- a/drivers/place/booking_notifier.cr +++ b/drivers/place/booking_notifier.cr @@ -295,8 +295,8 @@ class Place::BookingNotifier < PlaceOS::Driver send_to << email if email end - if booking_details.action == "approved" - logger.debug { "sending approved notification for booking #{booking_details.id}" } + if booking_details.action == "approved" || (booking_details.action == "metadata_changed" && booking_details.extension_data.dig?("details", "status").try(&.as_s) == "approved") + logger.debug { "sending approved notification for booking #{booking_details.id} (action: #{booking_details.action})" } mailer.send_template( to: send_to, template: {"bookings", third_party ? "booked_by_notify#{@template_suffix}" : "booking_notify#{@template_suffix}"}, @@ -312,8 +312,8 @@ class Place::BookingNotifier < PlaceOS::Driver attachments: attachments ) else - # metadata_changed but not a cancellation - skip notification - logger.debug { "ignoring booking #{booking_details.id}: metadata_changed action but status is '#{booking_details.extension_data.dig?("details", "status")}' (not cancelled)" } + # metadata_changed but not an approval or cancellation - skip notification + logger.debug { "ignoring booking #{booking_details.id}: metadata_changed action but status is '#{booking_details.extension_data.dig?("details", "status")}' (not approved or cancelled)" } return end staff_api.booking_state(booking_details.id, "notified", booking_details.instance).get From 1b779031f4b0df47b9f259581bb70da94745d7ea Mon Sep 17 00:00:00 2001 From: root Date: Wed, 3 Dec 2025 12:39:48 +0000 Subject: [PATCH 3/5] chore: remove docker-compose.yml and harness from version control --- docker-compose.yml | 74 ----------------------- harness | 142 --------------------------------------------- 2 files changed, 216 deletions(-) delete mode 100644 docker-compose.yml delete mode 100755 harness diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index c1974446079..00000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,74 +0,0 @@ -x-build-client-env: &build-client-env - PLACEOS_BUILD_HOST: ${PLACEOS_BUILD_HOST:-build} - PLACEOS_BUILD_PORT: ${PLACEOS_BUILD_PORT:-3000} - -services: - # Driver test harness - drivers: - image: placeos/drivers-spec:latest - restart: always - container_name: placeos-drivers - hostname: drivers - depends_on: - - build - - redis - - install-shards - ports: - - 127.0.0.1:8085:8080 - - 127.0.0.1:4444:4444 - volumes: - - ${PWD}/.logs:/app/report_failures - - ${PWD}/repositories:/app/repositories - - ${PWD}:/app/repositories/local - environment: - <<: *build-client-env - CI: ${CI:-} - CRYSTAL_PATH: lib:/lib/local-shards:/usr/share/crystal/src - REDIS_URL: redis://redis:6379 - TZ: $TZ - cap_add: - - "SYS_PTRACE" - security_opt: - - "seccomp:unconfined" - - build: - image: placeos/build:${PLACE_BUILD_TAG:-nightly} - restart: always - hostname: build - volumes: - - ${PWD}/repositories:/app/repositories - - ${PWD}:/app/repositories/local - - ${PWD}/binaries:/app/bin/drivers - environment: - AWS_REGION: ${AWS_REGION:-ap-southeast-2} - AWS_S3_BUCKET: ${AWS_S3_BUCKET:-placeos-drivers} - AWS_KEY: ${AWS_KEY} - AWS_SECRET: ${AWS_SECRET} - GIT_DISCOVERY_ACROSS_FILESYSTEM: 1 - PLACEOS_BUILD_LOCAL: 1 - PLACEOS_ENABLE_TRACE: 1 - TZ: $TZ - BUILD_SERVICE_DISABLED: ${BUILD_SERVICE_DISABLED:-true} - - redis: - image: eqalpha/keydb - restart: always - hostname: redis - environment: - TZ: $TZ - - # Ensures shards are installed. - install-shards: - image: placeos/crystal:${CRYSTAL_VERSION:-latest} - restart: "no" - working_dir: /wd - entrypoint: '' - command: sh -c 'shards check -q || shards install' - environment: - SHARDS_OPTS: "--ignore-crystal-version" - volumes: - - ${PWD}/shard.lock:/wd/shard.lock - - ${PWD}/shard.yml:/wd/shard.yml - - ${PWD}/shard.override.yml:/wd/shard.override.yml - - ${PWD}/.shards:/wd/.shards - - ${PWD}/lib:/wd/lib diff --git a/harness b/harness deleted file mode 100755 index 8934361abc5..00000000000 --- a/harness +++ /dev/null @@ -1,142 +0,0 @@ -#! /usr/bin/env bash - -# `e`: fail script if a command's exitcode is non-zero -# `u`: fail script if a variable is unset (unitialized) -set -eu - -say_done() { - printf "░░░ Done.\n" -} - -fail() { - echo "${@}" >&2 - exit 1 -} - -# Called when Ctrl-C is sent -function trap_ctrlc () -{ - echo ">~" - echo "░░░ Cleaning up..." - down - exit 2 -} - -trap "trap_ctrlc" 2 - -up() { - echo '░░░ PlaceOS Driver Harness' - echo '░░░ -> Pulling latest code...' - git pull - echo '░░░ -> Pulling latest images...' - docker compose pull - echo '░░░ -> Starting environment...' - docker compose up -d - printf "░░░ The harness can be found at http://localhost:8085/index.html\n" - echo '░░░ Stop the harness with `harness down`' - say_done -} - -down() { - echo '░░░ Stopping PlaceOS Driver Harness...' - docker compose down --remove-orphans &> /dev/null - say_done -} - -format() { - echo '░░░ Running `crystal tool format` over `drivers` and `repositories`' - docker compose run \ - -v "${PWD}/drivers:/wd/drivers" \ - -v "${PWD}/repositories:/wd/repositories" \ - --no-deps \ - --rm \ - install-shards \ - crystal tool format - say_done -} - -report() { - echo '░░░ PlaceOS Driver Compilation Report' - echo '░░░ Pulling images...' - docker compose pull &> /dev/null - - # Ensure shards are satisfied before running the report - echo '░░░ Installing shards...' - docker compose run \ - --rm \ - install-shards > /dev/null - - echo '░░░ Starting environment...' - docker compose up -d &> /dev/null - - exit_code=0 - - echo '░░░ Starting report...' - docker exec placeos-drivers report $@ || exit_code=$? - - down - exit ${exit_code} -} - -build() { - docker compose run \ - --rm \ - --no-deps \ - -v "${PWD}/repositories:/app/repositories" \ - -v "${PWD}/drivers:/app/repositories/drivers" \ - --entrypoint="/app/scripts/entrypoint.sh" \ - build build $@ -} - -usage() { - cat < Date: Thu, 11 Dec 2025 09:54:57 +1100 Subject: [PATCH 4/5] revert .gitignore --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index b446a0cff04..4313fa25e98 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,3 @@ lib .logs repositories/* src -docker-compose.yml -harness From 6a932b8b2629e21d03c55d4003a0a268ae0a7a40 Mon Sep 17 00:00:00 2001 From: Stephen von Takach Date: Thu, 11 Dec 2025 09:56:42 +1100 Subject: [PATCH 5/5] Revert "chore: remove docker-compose.yml and harness from version control" This reverts commit 1b779031f4b0df47b9f259581bb70da94745d7ea. --- docker-compose.yml | 74 +++++++++++++++++++++++ harness | 142 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 docker-compose.yml create mode 100755 harness diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000000..c1974446079 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,74 @@ +x-build-client-env: &build-client-env + PLACEOS_BUILD_HOST: ${PLACEOS_BUILD_HOST:-build} + PLACEOS_BUILD_PORT: ${PLACEOS_BUILD_PORT:-3000} + +services: + # Driver test harness + drivers: + image: placeos/drivers-spec:latest + restart: always + container_name: placeos-drivers + hostname: drivers + depends_on: + - build + - redis + - install-shards + ports: + - 127.0.0.1:8085:8080 + - 127.0.0.1:4444:4444 + volumes: + - ${PWD}/.logs:/app/report_failures + - ${PWD}/repositories:/app/repositories + - ${PWD}:/app/repositories/local + environment: + <<: *build-client-env + CI: ${CI:-} + CRYSTAL_PATH: lib:/lib/local-shards:/usr/share/crystal/src + REDIS_URL: redis://redis:6379 + TZ: $TZ + cap_add: + - "SYS_PTRACE" + security_opt: + - "seccomp:unconfined" + + build: + image: placeos/build:${PLACE_BUILD_TAG:-nightly} + restart: always + hostname: build + volumes: + - ${PWD}/repositories:/app/repositories + - ${PWD}:/app/repositories/local + - ${PWD}/binaries:/app/bin/drivers + environment: + AWS_REGION: ${AWS_REGION:-ap-southeast-2} + AWS_S3_BUCKET: ${AWS_S3_BUCKET:-placeos-drivers} + AWS_KEY: ${AWS_KEY} + AWS_SECRET: ${AWS_SECRET} + GIT_DISCOVERY_ACROSS_FILESYSTEM: 1 + PLACEOS_BUILD_LOCAL: 1 + PLACEOS_ENABLE_TRACE: 1 + TZ: $TZ + BUILD_SERVICE_DISABLED: ${BUILD_SERVICE_DISABLED:-true} + + redis: + image: eqalpha/keydb + restart: always + hostname: redis + environment: + TZ: $TZ + + # Ensures shards are installed. + install-shards: + image: placeos/crystal:${CRYSTAL_VERSION:-latest} + restart: "no" + working_dir: /wd + entrypoint: '' + command: sh -c 'shards check -q || shards install' + environment: + SHARDS_OPTS: "--ignore-crystal-version" + volumes: + - ${PWD}/shard.lock:/wd/shard.lock + - ${PWD}/shard.yml:/wd/shard.yml + - ${PWD}/shard.override.yml:/wd/shard.override.yml + - ${PWD}/.shards:/wd/.shards + - ${PWD}/lib:/wd/lib diff --git a/harness b/harness new file mode 100755 index 00000000000..8934361abc5 --- /dev/null +++ b/harness @@ -0,0 +1,142 @@ +#! /usr/bin/env bash + +# `e`: fail script if a command's exitcode is non-zero +# `u`: fail script if a variable is unset (unitialized) +set -eu + +say_done() { + printf "░░░ Done.\n" +} + +fail() { + echo "${@}" >&2 + exit 1 +} + +# Called when Ctrl-C is sent +function trap_ctrlc () +{ + echo ">~" + echo "░░░ Cleaning up..." + down + exit 2 +} + +trap "trap_ctrlc" 2 + +up() { + echo '░░░ PlaceOS Driver Harness' + echo '░░░ -> Pulling latest code...' + git pull + echo '░░░ -> Pulling latest images...' + docker compose pull + echo '░░░ -> Starting environment...' + docker compose up -d + printf "░░░ The harness can be found at http://localhost:8085/index.html\n" + echo '░░░ Stop the harness with `harness down`' + say_done +} + +down() { + echo '░░░ Stopping PlaceOS Driver Harness...' + docker compose down --remove-orphans &> /dev/null + say_done +} + +format() { + echo '░░░ Running `crystal tool format` over `drivers` and `repositories`' + docker compose run \ + -v "${PWD}/drivers:/wd/drivers" \ + -v "${PWD}/repositories:/wd/repositories" \ + --no-deps \ + --rm \ + install-shards \ + crystal tool format + say_done +} + +report() { + echo '░░░ PlaceOS Driver Compilation Report' + echo '░░░ Pulling images...' + docker compose pull &> /dev/null + + # Ensure shards are satisfied before running the report + echo '░░░ Installing shards...' + docker compose run \ + --rm \ + install-shards > /dev/null + + echo '░░░ Starting environment...' + docker compose up -d &> /dev/null + + exit_code=0 + + echo '░░░ Starting report...' + docker exec placeos-drivers report $@ || exit_code=$? + + down + exit ${exit_code} +} + +build() { + docker compose run \ + --rm \ + --no-deps \ + -v "${PWD}/repositories:/app/repositories" \ + -v "${PWD}/drivers:/app/repositories/drivers" \ + --entrypoint="/app/scripts/entrypoint.sh" \ + build build $@ +} + +usage() { + cat <