{"id":18685595,"url":"https://github.com/nitorcreations/nversary","last_synced_at":"2026-05-02T02:32:13.241Z","repository":{"id":38679682,"uuid":"177108339","full_name":"NitorCreations/nversary","owner":"NitorCreations","description":"nversary congratulates people on their work anniversary in Slack","archived":false,"fork":false,"pushed_at":"2024-01-09T20:46:29.000Z","size":3539,"stargazers_count":0,"open_issues_count":18,"forks_count":1,"subscribers_count":34,"default_branch":"master","last_synced_at":"2024-12-28T00:29:55.772Z","etag":null,"topics":["hacktoberfest","serverless-framework","slack"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NitorCreations.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-22T09:12:09.000Z","updated_at":"2023-12-06T17:26:00.000Z","dependencies_parsed_at":"2023-02-18T13:16:21.494Z","dependency_job_id":"43f92969-ecf9-43de-a83a-5f4998032511","html_url":"https://github.com/NitorCreations/nversary","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NitorCreations%2Fnversary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NitorCreations%2Fnversary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NitorCreations%2Fnversary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NitorCreations%2Fnversary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NitorCreations","download_url":"https://codeload.github.com/NitorCreations/nversary/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239541852,"owners_count":19656102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","serverless-framework","slack"],"created_at":"2024-11-07T10:23:19.592Z","updated_at":"2026-05-02T02:32:13.222Z","avatar_url":"https://github.com/NitorCreations.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nversary - work anniversary notifier\n\nnversary congratulates people on their work anniversary in Slack.\n\n## Functionality\n\nAnniversary messages are sent on working days only, with a maximum of 3 messages per day. If there are more than 3 anniversaries on nearby dates, they are spread out so that people with longer tenure get the message closest to their actual anniversary day.\n\n## Instructions\n\nHow to set up and configure nversary\n\n### Build\n\nBuild and package the Lambda artifact as a local zip file for Terraform to deploy.\n\nThe artifact is created by Task at:\n\n- `build/dev/nversary.zip`\n- `build/prod/nversary.zip`\n\n### AWS Account\n\nAn AWS Account is required. If you don't have one, create it at \u003chttps://aws.amazon.com/\u003e\n\n### People data (S3 object)\n\nPeople data is read from `s3://$PEOPLE_S3_BUCKET/$PEOPLE_S3_KEY`.\n\nExpected shape:\n\n```json\n{\n  \"people\": [\n    {\n      \"fullName\": \"Example Person\",\n      \"email\": \"example.person@example.com\",\n      \"presence\": [{ \"start\": \"2018-02-01\" }],\n      \"position\": \"Senior Consultant\",\n      \"businessUnit\": \"Technology\",\n      \"profileImageUrl\": \"https://example.com/image.jpg\",\n      \"slackId\": \"U0123456789\"\n    }\n  ]\n}\n```\n\nNotes:\n\n- `slackId` is optional but recommended; when present, nversary mentions that Slack user directly.\n- If `slackId` is missing, nversary falls back to matching Slack users by `email`.\n- `profileImageUrl` is optional.\n\n### Slack\n\n- Go to \u003chttps://api.slack.com/apps\u003e and click Create New App, give your app a name and attach it to a workspace.\n- In OAuth \u0026 Permissions, add bot token scopes:\n    - `chat:write`\n    - `users:read`\n    - `users:read.email`\n- Install the app to the workspace and save the Bot User OAuth Token.\n- Invite bot to the target channel: `/invite @botname`\n- Store credentials to AWS SSM Parameter Store as `SecureString`.\n\nThe JSON in SSM Parameter Store looks similar to this:\n\n```json\n{\n    \"slack\": {\n        \"webhookUrl\": \"\",\n        \"appToken\": \"xoxb-32896343824-849329924324243-lkjrewrwXKhgkDkfobo4dore\",\n        \"channelId\": \"JO3KFSO5\"\n    }\n}\n```\n\n- `webhookUrl` is currently unused by the runtime (kept for backward compatibility with the existing config model).\n- `appToken` is _Bot User OAuth Token_ from _Features/OAuth \u0026 Permissions_.\n- `channelId` is the identifier for channel where messages are sent. You can obtain this from Slack UI/Chat app.\n\n### Deploy to AWS\n\nnversary uses Terraform for deployment.\n\nTerraform layout:\n\n- `terraform/modules/nversary_notifier` reusable module\n- `terraform/infra/envs/dev` development environment root\n- `terraform/infra/envs/prod` production environment root\n- `terraform/remote-state` bootstrap for Terraform backend state bucket\n\nBoth environments use an S3 backend (`backend \"s3\" {}`) configured in:\n\n- `terraform/infra/envs/dev/backend.tf`\n- `terraform/infra/envs/prod/backend.tf`\n\nDeployment values come from Terraform input variables and static values in `terraform/infra/envs/*/main.tf`:\n\n- `name` and `environment`\n- `runtime` and `timeout`\n- `people_s3_bucket` and `people_s3_key` (pass at apply/plan time)\n- `ssm_parameter_name` (pass at apply/plan time)\n- `artifact_file` (local path to the Lambda zip)\n- `log_retention_days`\n\nCurrent environment scheduling:\n\n- `dev`: disabled schedule (`cron(0 0 31 2 ? *)`)\n- `prod`: daily at `03:50 UTC` (`cron(50 3 * * ? *)`)\n\n### Slack dry-run by environment\n\nSlack send behavior is controlled by the Lambda environment variable `SLACK_DRY_RUN`.\n\n- `dev`: configurable at deploy time via `SLACK_DRY_RUN`, defaults to `true`\n- `prod`: always `false` (messages are always sent)\n\nExamples:\n\n```shell\n# dev default (dry-run enabled)\ntask deploy:dev\n\n# dev override (send real Slack messages)\nSLACK_DRY_RUN=false task deploy:dev\n\n# prod (always dry-run=false)\ntask deploy:prod\n```\n\n### Deployment prerequisites\n\nInstall:\n\n- [Task](https://taskfile.dev/)\n- Terraform (`\u003e= 1.14.0`)\n- Node.js + npm\n\nSet required environment variables:\n\n```shell\nexport PEOPLE_S3_BUCKET=your-people-bucket\nexport PEOPLE_S3_KEY=path/to/people.json\nexport SSM_PARAMETER_NAME=/path/to/slack-config\n```\n\n### Deploy with Task\n\nPlan/apply for development:\n\n```shell\ntask deploy:plan:dev\ntask deploy:dev\n```\n\nPlan/apply for production:\n\n```shell\ntask deploy:plan:prod\ntask deploy:prod\n```\n\nTask workflow does all of the following:\n\n- validates required environment variables\n- bootstraps Terraform remote state from `terraform/remote-state/main.tf` if needed\n- packages Lambda artifact zip for the selected environment\n- runs Terraform `init`, `plan`, and `apply` in the matching environment root\n\n### Unit testing\n\n```shell\nnpm run test\n```\n\n### End to end testing\n\nYou can test the Lambda function from AWS Lambda console by creating a test event with a `dateString` attribute.\nThe date string should be in `yyyy-MM-dd` format.\nSetting `sendNow` to true, will send messages immediately. An example of test event:\n\n```json\n{\n    \"dateString\": \"2022-04-25\",\n    \"sendNow\": true\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitorcreations%2Fnversary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnitorcreations%2Fnversary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitorcreations%2Fnversary/lists"}