Commit graph

68 commits

Author SHA1 Message Date
Adam Moussa
debac9f8a7 Add admin slash commands for shift and roster management (#39)
- /oncall admin override <date> <ext> — assign a shift
- /oncall admin open <date> — mark shift as open
- /oncall admin clear <date> — remove override, revert to weekly
- /oncall admin roster add/remove/rename — manage roster entries
- Admin access gated by admin_users list in DynamoDB CONFIG
- Help message shows admin commands for admin users
2026-05-12 15:50:24 -04:00
Adam Moussa
e9b55d357b Disallow past shifts and add day/night labels (#43, #42)
- Reject /oncall pick and /oncall drop for past dates
- Show ephemeral error when stale pickup buttons are clicked
- Hide pickup buttons for dates in the past
- Add explicit "Day (8am-5pm)" and "Night (5pm-8am)" labels to
  schedule lines, pickup buttons, and shift change notifications
2026-05-12 15:48:35 -04:00
Adam Moussa
9dd7cbd0f8 Add schedule post live-update and old post deletion (#40, #41)
- Store schedule message timestamp in DynamoDB (SCHEDULE_POST record)
- Delete previous week's schedule post before posting the new one
- Live-update the schedule post via chat_update after any
  pick/drop/swap/button-pickup so it always reflects current state
2026-05-12 15:46:14 -04:00
Adam Moussa
b137334c5b Merge ring-scheduler-3cx as 4th Lambda function
- Add afterhours-ring-scheduler Lambda with 4 EventBridge rules
  (daily 8am EST/EDT + weekend 5pm EST/EDT) for 3CX ring group
  routing updates
- Extract shared ring_scheduler.py module for direct ring group
  updates from both the scheduled Lambda and the Slack bot
- Replace cross-Lambda invoke with direct update_ring_group() call
  in the Slack bot — eliminates lambda:InvokeFunction dependency
- Use RingGroup API (correct) instead of Queue API (was wrong in
  the original ring-scheduler repo)
- Eliminate YAML config fallback — DynamoDB is the sole schedule
  source
- Add RingGroupNumber CloudFormation parameter
2026-05-12 15:44:12 -04:00
Adam Moussa
7979e2a4e7 Migrate secrets from SSM Parameter Store to Secrets Manager
- Slack bot token and signing secret now read from Secrets Manager
- 3CX credentials (domain, client-id, client-secret) moved to
  Secrets Manager under afterhours-shift-manager/3cx-* prefix
- Channel ID is now a non-secret CloudFormation parameter (ShiftChannel)
- Add shared secrets.py helper for Secrets Manager reads
- Remove SSM and KMS IAM policies, add secretsmanager:GetSecretValue
2026-05-12 15:41:44 -04:00
Adam Moussa
0fed60248a Restructure src/ to per-function layout with shared Layer
Move from flat src/ to per-function directories:
- src/slack-bot/ — Slack Bolt Lambda handler
- src/weekly-post/ — Monday schedule + pay post
- src/roster-sync/ — Daily 3CX roster sync
- src/shared/ — Lambda Layer with schedule, blocks, three_cx_client

Each function has its own requirements.txt and CodeUri. Shared
modules are deployed as a SAM Layer (afterhours-shared) importable
as `from shared.X import Y`.
2026-05-12 15:39:28 -04:00
Adam Moussa
3de9243f6b Add arm64, log retention, and compliance fixes
- Set arm64 architecture globally for all Lambda functions
- Add explicit CloudWatch log groups with 60-day retention
- Add missing WeeklyPostFunctionArn to stack outputs
- Add Dependabot assignees for both ecosystems
- Add samconfig.toml.example for onboarding
2026-05-12 15:36:22 -04:00
Adam Moussa
f26fe978b5
Disable Slack version notification (#55) (#60)
Dependabot PRs are merging frequently, causing daily version bump
posts to flood the channel. Disable the Slack post step until #55
is resolved.
2026-05-08 20:15:37 -04:00
dependabot[bot]
9920cc9d2f
Update boto3 requirement from >=1.43.4 to >=1.43.6 (#56)
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.4...1.43.6)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.6
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-08 22:26:48 +00:00
Adam Moussa
e55e065351
Remove CodePipeline files (#59)
Deploys now run via GitHub Actions (cd-sam.yaml). The CodePipeline
stack and its IAM roles have been deleted from AWS.
2026-05-08 22:11:18 +00:00
Adam Moussa
b750f1aaee
Add GitHub Actions deploy workflow (#58)
* Add GitHub Actions deploy workflow (OIDC)

* Add permissions block for OIDC token exchange

* Add concurrency control to prevent parallel deploys
2026-05-08 17:07:49 -04:00
Adam Moussa
c741924ee7
Add CI workflow and apply ruff formatting (#57) 2026-05-08 15:46:51 -04:00
Adam Moussa
7aefcb9d68
Update Dependabot: remove assignees, group minor/patch updates (#54) 2026-05-08 14:24:39 -04:00
Adam Moussa
6ac4c0ed7e
Remove wrapper workflow — using required workflow via org ruleset (#53) 2026-05-06 19:59:12 -04:00
dependabot[bot]
f7ea5f1b1a
Bump actions/checkout from 4 to 6 (#45)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-06 18:44:19 -04:00
dependabot[bot]
feca3c7c81
Update boto3 requirement from >=1.43.2 to >=1.43.4 (#51)
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.2...1.43.4)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-06 18:21:33 -04:00
Adam Moussa
843cfd73b3
Add Claude Code review workflow (#52) 2026-05-06 18:11:30 -04:00
Adam Moussa
b081191114
Merge pull request #50 from Sea-Haven-Industries/feature/fix-version-bump-workflow
Fix version bump timezone bug and dynamic canvas URL
2026-05-04 16:13:13 -04:00
Adam Moussa
fbabab9692 Fix timezone mismatch in version bump PR filter and use dynamic canvas URL
The date comparison used git's author date in its stored timezone
(e.g. -04:00) against GitHub API mergedAt values in UTC (Z suffix).
Lexicographic string comparison across different timezone formats
caused every PR from the tagged commit's day to be re-included in
subsequent versions. Normalize to UTC with format-local so both
sides match.

Also replace the hardcoded canvas URL with the CANVAS_ID env var
already available in the step.
2026-05-04 15:26:36 -04:00
Adam Moussa
5bc5cc9131
Merge pull request #49 from Sea-Haven-Industries/feature/dependabot-auto-assign
Auto-assign Dependabot PRs
2026-05-02 17:28:28 -04:00
Adam Moussa
94fca2c773 Auto-assign Dependabot PRs to amoussa1229 2026-05-02 17:26:42 -04:00
Adam Moussa
35550b96c1
Merge pull request #48 from Sea-Haven-Industries/dependabot/pip/requests-gte-2.33.1
Update requests requirement from >=2.31.0 to >=2.33.1
2026-05-02 17:25:32 -04:00
Adam Moussa
61fb7c52bb
Merge pull request #47 from Sea-Haven-Industries/dependabot/pip/slack-bolt-gte-1.28.0-and-lt-2.0
Update slack-bolt requirement from <2.0,>=1.18.0 to >=1.28.0,<2.0
2026-05-02 17:25:29 -04:00
dependabot[bot]
db909d4dfe
Update slack-bolt requirement from <2.0,>=1.18.0 to >=1.28.0,<2.0
Updates the requirements on [slack-bolt](https://github.com/slackapi/bolt-python) to permit the latest version.
- [Release notes](https://github.com/slackapi/bolt-python/releases)
- [Commits](https://github.com/slackapi/bolt-python/compare/v1.18.0...v1.28.0)

---
updated-dependencies:
- dependency-name: slack-bolt
  dependency-version: 1.28.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-02 21:23:57 +00:00
dependabot[bot]
dec6a7c924
Update requests requirement from >=2.31.0 to >=2.33.1
Updates the requirements on [requests](https://github.com/psf/requests) to permit the latest version.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.31.0...v2.33.1)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.33.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-02 21:23:48 +00:00
Adam Moussa
398e14b579
Merge pull request #46 from Sea-Haven-Industries/dependabot/pip/boto3-gte-1.43.2
Update boto3 requirement from >=1.28.0 to >=1.43.2
2026-05-02 17:22:46 -04:00
dependabot[bot]
596a1ebaa3
Update boto3 requirement from >=1.28.0 to >=1.43.2
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.28.0...1.43.2)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-02 21:17:18 +00:00
Adam Moussa
0c4fdfa49a
Merge pull request #44 from Sea-Haven-Industries/feature/add-dependabot-config
Add Dependabot version update configuration
2026-05-02 17:16:03 -04:00
Adam Moussa
ad28e0f2a6 Add Dependabot version update configuration 2026-05-02 17:14:42 -04:00
Adam Moussa
5018494069
Update README with CI/CD pipeline, pay commands, and Lambda inventory (#38) 2026-05-01 16:32:50 -04:00
Adam Moussa
8fe4b7629c
Fix CodeBuild environment type for ARM image (#37) 2026-05-01 16:28:13 -04:00
Adam Moussa
6d6130c1a6
Add CodePipeline CI/CD, remove Git sync config (#36) (#36)
- Added reusable pipeline.yaml (CodePipeline + CodeBuild + CloudFormation deploy)
- Added buildspec.yml for SAM build/package
- Removed deployment-config.yaml and untracked samconfig.toml (Git sync artifacts)
- Restored samconfig.toml to .gitignore
2026-05-01 16:18:56 -04:00
Adam Moussa
bdc97e0877
Add Git sync deployment config file (#35) 2026-05-01 16:09:14 -04:00
Adam Moussa
0f37558487
Track samconfig.toml for CloudFormation Git sync deployments (#33) 2026-05-01 15:54:30 -04:00
Adam Moussa
61074dc7cc
Fix shift pickup showing error despite succeeding (#31) (#32)
Two root causes:
- claim_open_shift ConditionExpression failed when no OVERRIDE record
  existed (shift available via weekly fallback). Added attribute_not_exists
  check so claims succeed for both missing and OPEN overrides.
- Slack ack timeout: chat_postMessage took too long before respond() was
  called, causing Slack to show an error. Moved respond() first and made
  channel notifications best-effort with try/except.
2026-05-01 15:16:11 -04:00
Adam Moussa
a85eb0afd9
Default to patch version bumps, add minor bump option (#30)
Scheduled runs auto-bump patch (v1.7.0 -> v1.7.1). Manual triggers
get a dropdown to choose patch or minor bump.
2026-05-01 15:06:04 -04:00
Adam Moussa
55697748cb
Use semver auto-increment for daily version bumps (#29)
Replaces date-based versions (v2026.05.01) with semver minor bumps
(v1.7.0 -> v1.8.0) to stay consistent with the project's existing
version history.
2026-05-01 15:00:51 -04:00
Adam Moussa
7116458efb
Fix printf flag parsing in version bump workflow (#28) 2026-05-01 14:53:47 -04:00
Adam Moussa
f92f2ed72e
Add pull-requests read permission to version bump workflow (#27) 2026-05-01 14:51:33 -04:00
Adam Moussa
ca3b3096fc
Skip DST guard on manual workflow_dispatch triggers (#26) 2026-05-01 14:49:01 -04:00
Adam Moussa
b08a532da3
Polish version notifications and sync changelog canvas (#21) (#25)
Reworks the daily version bump workflow to:
- Pull merged PR titles via gh CLI instead of raw commit messages
- Post a polished, non-technical channel message with a link to the
  changelog canvas
- Prepend the new version entry to the Slack canvas via canvases.edit
  API so the canvas stays in sync automatically

Channel message format:
  "After-Hours Scheduler has been updated to vXXXX.XX.XX
   Here's a brief summary of what changed:
   • ...
   Click here to read the full changelog"
2026-05-01 14:47:16 -04:00
Adam Moussa
769b9e5acd
Change deploy notifications to daily version bumps (#24)
Replaces per-push notifications with a daily 6pm ET cron job that
batches all commits since the last version tag into a single Slack
message. Tags main with a date-based version (v2026.05.01) so there
is at most one version bump per day. Includes DST guard matching the
pattern used by the other scheduled Lambdas.
2026-05-01 14:37:54 -04:00
Adam Moussa
5e052d424d
Add GitHub Actions workflow for deploy notifications (#23)
Posts a Slack message to the schedule channel whenever code is pushed
to main. Uses the existing Slack bot token stored as a GitHub secret.
2026-05-01 14:32:53 -04:00
Adam Moussa
7b2275a430
Post shift change notifications to the schedule channel (#21) (#22)
Slash command handlers (drop, pick, swap) were posting notifications to
command["channel_id"] — wherever the command was run. If someone ran
/oncall drop from a DM, the notification went there instead of the
schedule channel. Pickup buttons didn't have this problem because
body["channel"]["id"] is always the channel where the button lives.

Added SHIFT_CHANNEL_PARAM to the SlackBotFunction env vars, read it on
cold start, and route all slash command shift-change notifications to
the configured schedule channel.

Closes #21
2026-05-01 14:15:56 -04:00
Adam Moussa
1e90e0eaa2
Fix race condition allowing multiple people to pick up the same shift (#19) (#20)
The pickup button handler used an unconditional put_item, so concurrent
clicks would both succeed with last-write-wins. Added claim_open_shift()
which uses a DynamoDB ConditionExpression to only write if the shift is
still OPEN. The button handler now returns an ephemeral "already taken"
message when the condition fails.

Closes #19
2026-05-01 14:09:39 -04:00
Adam Moussa
fe6b780e12
Fix weekly schedule starting from today instead of Monday (#18)
The handler passed `now` as start_date, so mid-week runs showed
14 days from today instead of Mon–Sun x2. Also, day names were
derived from a static index (DAY_ORDER[i%7]) which assumed
index 0 = Monday — when start_date wasn't Monday, Saturday and
Sunday were mislabeled as Monday and Tuesday.

Fix: pass this week's Monday from the handler, and derive day
names from the actual date via strftime instead of a static list.

Fixes #17
2026-04-08 13:36:34 -04:00
Adam Moussa
14f9723a87
Change pay report recipient to payroll@seahaven.com (#16)
Update PAYROLL_RECIPIENTS env var from adam@seahaven.com to
payroll@seahaven.com so weekly Bonus Pay Summary emails go
directly to the payroll team. Fixes #12
2026-04-08 13:24:45 -04:00
Adam Moussa
6ad952c498
Remove shift count column from pay email, update footer text (#15)
- Remove the Shifts column from the Bonus Pay Summary email table (fixes #14)
- Change footer from "After-Hours Shift Manager" to "Sea Haven Industries" (fixes #13)
- Update README with pay report email section
2026-04-08 13:22:28 -04:00
Adam Moussa
9e2eab6953 DM pay reports to admin, rename email to Bonus Pay Summary
- Pay summary sent as DM to designated user instead of channel
- Email shows only per-person totals, no shift breakdown
- Renamed email subject/header to "Bonus Pay Summary"
2026-04-07 19:07:44 -04:00
Adam Moussa
a570a96311 Broaden SES permission to all verified identities 2026-04-07 19:01:12 -04:00