diff --git a/.github/workflows/bounty-program-commands.yml b/.github/workflows/bounty-program-commands.yml index 433f7d953..645e0c90d 100644 --- a/.github/workflows/bounty-program-commands.yml +++ b/.github/workflows/bounty-program-commands.yml @@ -14,12 +14,18 @@ on: types: - created +env: + BOUNTY_PROGRAM_LABELS_JSON: | + [ + {"name": "bounty", "color": "0e8a16", "description": "Participation in the Bounty Program"} + ] + jobs: guard-against-unauthorized-use: if: > github.actor != ('aeworxet' || 'thulieblack') && ( - contains(github.event.comment.body, '/bounty' ) + startsWith(github.event.comment.body, '/bounty' ) ) runs-on: ubuntu-latest @@ -46,15 +52,10 @@ jobs: if: > github.actor == ('aeworxet' || 'thulieblack') && ( - contains(github.event.comment.body, '/bounty' ) + startsWith(github.event.comment.body, '/bounty' ) ) runs-on: ubuntu-latest - env: - BOUNTY_PROGRAM_LABELS_JSON: | - [ - {"name": "bounty", "color": "0e8a16", "description": "Participation in the Bounty Program"} - ] steps: - name: Add label `bounty` @@ -88,3 +89,38 @@ jobs: repo: context.repo.repo, labels: [BOUNTY_PROGRAM_LABELS[0].name] }) + + remove-label-bounty: + if: > + github.actor == ('aeworxet' || 'thulieblack') && + ( + startsWith(github.event.comment.body, '/unbounty' ) + ) + + runs-on: ubuntu-latest + + steps: + - name: Remove label `bounty` + uses: actions/github-script@v6 + + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + const BOUNTY_PROGRAM_LABELS = JSON.parse(process.env.BOUNTY_PROGRAM_LABELS_JSON); + let LIST_OF_LABELS_FOR_ISSUE = await github.rest.issues.listLabelsOnIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + LIST_OF_LABELS_FOR_ISSUE = LIST_OF_LABELS_FOR_ISSUE.data.map(key => key.name); + + if (LIST_OF_LABELS_FOR_ISSUE.includes(BOUNTY_PROGRAM_LABELS[0].name)) { + console.log('Removing label `bounty`...'); + github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: [BOUNTY_PROGRAM_LABELS[0].name] + }) + } diff --git a/.github/workflows/create-event-ad-hoc.yml b/.github/workflows/create-event-ad-hoc.yml index 8a5a0d1b4..e5f22c8d8 100644 --- a/.github/workflows/create-event-ad-hoc.yml +++ b/.github/workflows/create-event-ad-hoc.yml @@ -30,7 +30,7 @@ jobs: meeting_desc: ${{ github.event.inputs.desc }} meeting_banner: ${{ github.event.inputs.meeting_banner }} host: lpgornicki@gmail.com - alternative_host: "fmvilas@gmail.com,jonas-lt@live.dk,devlopergene@gmail.com,sibanda.thulie@gmail.com" + alternative_host: "fmvilas@gmail.com,jonas-lt@live.dk,devlopergene@gmail.com,sibanda.thulie@gmail.com,alejandra.olvera.novack@gmail.com,samir.amzani@gmail.com" issue_template_path: .github/workflows/create-event-helpers/issues_templates/ad-hoc.md create_zoom: true secrets: diff --git a/.github/workflows/slack-integration.yml b/.github/workflows/slack-integration.yml new file mode 100644 index 000000000..6bfa2fd7f --- /dev/null +++ b/.github/workflows/slack-integration.yml @@ -0,0 +1,45 @@ +name: Automatic Slack Management + +on: + push: + paths: + - '**/slack/**/*' + - 'MAINTAINERS.yaml' + - 'WORKING_GROUPS.yaml' + - '.github/workflows/slack-integration.yml' + +jobs: + deploy-changes-to-slack: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Deploy changes to Slack + run: | + cd .github/workflows/slack + terraform init + terraform apply \ + -var "slack_token=${{ secrets.SLACK_INFRA_TOKEN }}" \ + -auto-approve + - name: Check if there are any uncommitted changes + id: git-check + run: | + # Set the output should_push to true if there are uncommitted changes + if [ -n "$(git status --porcelain)" ]; then + echo "Changes detected" + echo "should_push=true" >> $GITHUB_OUTPUT + else + echo "No changes detected" + echo "should_push=false" >> $GITHUB_OUTPUT + fi + - name: Push changes to GitHub + if: steps.git-check.outputs.should_push == 'true' + uses: peter-evans/create-pull-request@38e0b6e68b4c852a5500a94740f0e535e0d7ba54 # use 4.2.4 https://github.com/peter-evans/create-pull-request/releases/tag/v4.2.4 + with: + token: ${{ secrets.GH_TOKEN }} + commit-message: 'chore(slack): update slack configuration' + committer: asyncapi-bot + author: asyncapi-bot + title: 'ci(slack): update slack configuration' + body: 'This PR was automatically created by the Automatic Slack Management GitHub Action.' + branch: 'chore/slack-update-${{ github.run_number }}' diff --git a/.github/workflows/slack/.terraform.lock.hcl b/.github/workflows/slack/.terraform.lock.hcl new file mode 100644 index 000000000..483c5f8a7 --- /dev/null +++ b/.github/workflows/slack/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/pablovarela/slack" { + version = "1.2.2" + constraints = "~> 1.0" + hashes = [ + "h1:0cQTyJPZUA2AYz+tKQ4z6Vbm0LwZbvtLOAsStWxFkIE=", + "h1:eNX77+dnJ7JRx9xX7WHMNy4QUxlcEXDUzldOunLDRNk=", + "zh:001870e887a1e29a328b87f6431444d8d60e3c7e958fae2e885fbfc4d345886a", + "zh:065ff64914739cb2942a5a133b2f6e37c3a4278199ca2416d4c578f4d5a12659", + "zh:383d283b2344732b1c2514c072f4d93de2fd0660d478381756f35ca1be69da41", + "zh:38a393a7c294e81f4e951a1bde494e79868144f82cdb9662e6d4e0428571bf54", + "zh:51c81d69806acb4048aef69dc2fa3e2464b4c86c68009e4de93814c42783e736", + "zh:5ad19e4173069c503a7fdc55fc84de2358d021536039e72efffd79f95dc4245e", + "zh:63b39c1d32a5cb0ce2afee114d43b1444653cc78b45d252e2c0031fbb0b0ffbf", + "zh:701a19598b3e554b08d203507c215b218aa21646ea70dd2e8f20e232cb1c138e", + "zh:77f854eec925a895f68ab8b744728fe6203f6a1771ef27200cfce67b6836f168", + "zh:8b7cd7311034eb35f0d4e1473048798aa826db2194ae159596846eda9b96c562", + "zh:ac3a062bd1502a2e9059a14e68b02f09cebcff8bda25a9b9dc5382919eddbf58", + "zh:b1f4f5fd6d88ca34f8d996898759213c9acf5498058c269d98ab0d1b7e91ce2d", + "zh:efb2befca31fe7a0682513077fcb43d3d50170661fb5b26b1920ee4f8fd9c6a6", + "zh:fdd9b048446fbc05363b75b607986be803ea36179a61d8151497a5c0f24d5630", + ] +} diff --git a/.github/workflows/slack/README.md b/.github/workflows/slack/README.md new file mode 100644 index 000000000..44625aa90 --- /dev/null +++ b/.github/workflows/slack/README.md @@ -0,0 +1,147 @@ +## Infrastructure for slack integration + +This directory contains the infrastructure for Slack integration. It is used to create/manage Slack channels and groups and invite users to Slack channels. The Slack integration is implemented using the [slack-terraform-provider](https://github.com/pablovarela/terraform-provider-slack). + +### Prerequisites + +- [A slack App](https://api.slack.com/apps) with the following scopes under `User Token Scopes` in `OAuth & Permissions`: + + Write Permissions: + - `channels:write` + - `groups:write` + - `usergroups:write` + + Read Permissions: + - `channels:read` + - `groups:read` + - `usergroups:read` + +> [!CAUTION] +> Try to use a bot to log into Slack to prevent any changes from being attributed to the workspace owner. This is due to using a `user token` for authentication, which does the changes on behalf of the user who created the token. + +- [API Token](https://api.slack.com/apps) after installing the app in your workspace. ( `xoxp-` ) + +- [Terraform](https://www.terraform.io/downloads.html) installed on your local machine. + +### Usage + +- Create a `terraform.tfvars` file in the `slack` directory with the following content: + +```hcl +slack_token = "xoxp-" +``` + +- Run the following commands to create the Slack resources: + +```bash +terraform init +terraform apply +``` + +> [!TIP] +> The `terraform apply` command will create the resources better to use `terraform plan` to see the changes before applying. + +### How it works + +Three main resources are created using the slack integration: + +- `slack_channel`: This resource creates a slack channel. The channels are defined in the [channels.yaml](./channels/channels.yaml) file. with the structure explained there. + +- `slack_usergroup`: This resource creates a Slack user group. The usergroups are defined in the [usergroups.yaml](./groups/groups.yaml) file, and their structure is explained there. + +> [!CAUTION] +> The user groups should be unique across the workspace (i.e., no channel, user, or user group should have the same handle). Also, in case of user groups mentioned in the yaml existing in the workspace, you have to run the following command to import it to terraform state: +> ```bash +> terraform import module.groups.slack_usergroup.[\"\"] +> +> # Example +> terraform import module.groups.slack_usergroup.wg_groups[\"Developer Experience\"] +> ``` + +- `slack_user`: This resource invites users to the Slack workspace. The users are defined in the [users.tf](./users/users.tf) file, and their structure is explained there. + +### Pitfalls + +- Use of bot token of the format `xoxo-` is not supported for creating user groups. +- The user group should be unique across the workspace (i.e., no channel, user, or user group should have the same handle). +- Please [import](#importing-existing-resources) the user groups to terraform state if they already exist in the workspace, as they **cannot be deleted** in Slack 😢. + +> [!IMPORTANT] +> The terraform state will overwrite any description, name, or topic change. It is better to manage the changes in the YAML files and then apply them. However, the terraform state will not affect bookmarks, pinned items, etc. + +### Importing existing resources + +In case you have existing resources such as channels, user groups in the workspace, you can import them to the terraform state by transforming the `json` response from the slack API. An example script can be seen below: + +```javascript +const fs = require('fs'); +const fetch = require('node-fetch'); + +const token = 'xoxp-'; + +const fetchResource = async (resource, url_params) => { + // convert the url_params to query string + const url = new URL(`https://slack.com/api/${resource}`); + Object.keys(url_params).forEach(key => url.searchParams.append(key, url_params[key])); + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Authorization': `Bearer ${token}` + } + }); + const data = await response.json(); + return data; +} + +async function main() { + const channels = await fetchResource('conversations.list', { exclude_archived: true }); + const usergroups = await fetchResource('usergroups.list', { include_users: true }); + + channels.channels.forEach(channel => { + console.log(`terraform import module.channels.slack_conversation.channels[\\"${channel.name}\\"] ${channel.id}`); + }); + + usergroups.usergroups.forEach(usergroup => { + console.log(`terraform import module.groups.slack_usergroup.wg_groups[\\"${usergroup.name}\\"] ${usergroup.id}`); + }); +} + + +main(); +``` + +### What all can be done? + +#### Groups + +The groups can be mentioned in the slack messages using the `@` syntax. Addition of groups can be done by adding the group to the [groups.yaml](./groups/groups.yaml) file. + +The following groups are being created currently: +- `tsc` + + This group is for the Technical Steering Committee members mentioned in the [TSC_MEMBERS](../../../TSC_MEMBERS.json) file. Can be used to mention all the TSC members at once. + +- `maintainers` + + This group is for the all maintainers of the repository mentioned in the [MAINTAINERS](../../../MAINTAINERS.yaml) file. Can be used to mention all the maintainers at once. + +- `studio` + + This group consists of members actively working on the studio project. + +- `coc_commitee` + + This group consists of members of the Code of Conduct committee. + +In addition to these groups are also being created for each working group mentioned in the [WORKING_GROUPS](../../../WORKING_GROUPS.yaml) file. Example: `@dx_wg`. + +We are also having groups for maintainers of each repository mentioned in the [MAINTAINERS](../../../MAINTAINERS.yaml) file. You can mention the maintainers of a repository using `@maintainers_`. Example: `@maintainers_studio`. + +#### Channels + +Two types of channels are being created currently: + +- General channels: The channels are defined in the [channels.yaml](./channels/channels.yaml) file with the structure explained there. + +- Working group channels: The working group channels are created for each working group mentioned in the [WORKING_GROUPS](../../../WORKING_GROUPS.yaml) file. The channels are created with the name `wg_` or custom nameas configured in the [WORKING_GROUPS](../../../WORKING_GROUPS.yaml) file. diff --git a/.github/workflows/slack/channels/channels.tf b/.github/workflows/slack/channels/channels.tf new file mode 100644 index 000000000..2f6f9d9ae --- /dev/null +++ b/.github/workflows/slack/channels/channels.tf @@ -0,0 +1,85 @@ +terraform { + required_providers { + slack = { + source = "pablovarela/slack" + version = "~> 1.0" + } + } +} + +variable "data_sources" { + default = { + tsc_members_user_ids = [] + maintainers_user_ids = [] + repo_maintainers = {} + } + description = "Data sources for the slack channels from the users module" +} + +locals { + channel_data = yamldecode(file("${path.module}/channels.yaml")) + channels = { + for channel in local.channel_data : channel.name => { + name = channel.name + topic = channel.topic + purpose = channel.purpose + + # if permanent_members is not provided, then it wil be taken from local with the name in data sources + permanent_members = lookup(channel, "permanent_members", lookup(var.data_sources, lookup(channel, "data_source", channel.name), [])) + is_private = channel.is_private + action_on_destroy = channel.action_on_destroy + + # if private channel, then kick all users on update else none + action_on_update_permanent_members = channel.is_private ? "kick" : "none" + adopt_existing_channel = true + } + } +} + +resource "slack_conversation" "channels" { + for_each = local.channels + name = each.value.name + topic = each.value.topic + purpose = each.value.purpose + permanent_members = each.value.permanent_members + + is_private = each.value.is_private + action_on_destroy = each.value.action_on_destroy + action_on_update_permanent_members = each.value.action_on_update_permanent_members + adopt_existing_channel = each.value.adopt_existing_channel +} + +locals { + working_groups_data = yamldecode(file("${path.module}/../../../../WORKING_GROUPS.yaml")).working_groups + wg_channels = { + for wg_data in local.working_groups_data : wg_data.name => { + name = lookup(lookup(lookup(wg_data, "slack", {}), "channel", {}), "handle", "wg-${replace(lower(wg_data.name), " ", "-")}") + purpose = lookup(lookup(lookup(wg_data, "slack", {}), "channel", {}), "description", lookup(wg_data, "description", "")) + topic = lookup(lookup(lookup(wg_data, "slack", {}), "channel", {}), "topic", "") + + permanent_members = concat([for member in wg_data.chairpersons : member.slack], [for member in wg_data.members : member.slack]) + is_private = false + + action_on_destroy = "archive" + action_on_update_permanent_members = "none" + adopt_existing_channel = true + } + } +} + +resource "slack_conversation" "wg_channels" { + for_each = local.wg_channels + name = each.value.name + topic = each.value.topic + purpose = each.value.purpose + permanent_members = each.value.permanent_members + + is_private = each.value.is_private + action_on_destroy = each.value.action_on_destroy + action_on_update_permanent_members = each.value.action_on_update_permanent_members + adopt_existing_channel = each.value.adopt_existing_channel +} + +output "wg_channels" { + value = slack_conversation.wg_channels +} \ No newline at end of file diff --git a/.github/workflows/slack/channels/channels.yaml b/.github/workflows/slack/channels/channels.yaml new file mode 100644 index 000000000..861911a19 --- /dev/null +++ b/.github/workflows/slack/channels/channels.yaml @@ -0,0 +1,255 @@ +# Channels: +# +# name - (Required) name of the public or private channel. +# topic - (Optional) topic for the channel. +# purpose - (Optional) purpose of the channel. +# permanent_members - (Optional) user IDs to add to the channel. +# is_private - (Optional) create a private channel instead of a public one. +# is_archived - (Optional) indicates a conversation is archived. Frozen in time. +# action_on_destroy - (Optional, Default archive) indicates whether the conversation should be archived or left behind on destroy. Valid values are archive | none. Note that when set to none the conversation will be left as it is and as a result any subsequent runs of terraform apply with the same name will fail. +# data_source - (Optional) data_source source to use for the list of user IDs to add to the channel. Valid values are maintainers_user_ids | tsc_user_ids right now. + +# NOTE:- +# 1. The channel name should be unique. +# 2. The user IDs should be valid and should be present in the workspace. +# 3. Either permanent_members or data_source should be provided to add users to the channel. +# 4. The default value for change in permanent_members is kick for private channels and nothing for public channels. +# 5. The default value for adopt_current_channels is true. + +- name: 01_introductions + topic: Welcome to our AsyncAPI Slack! Take a moment to introduce yourself. + purpose: Welcome to our AsyncAPI Slack! Take a moment to introduce yourself. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 02_general + topic: 'Talk here if your topic is not only about the spec, nor tools but kinda mix and involves AsyncAPI :slightly_smiling_face:' + purpose: This channel is for team-wide communication and announcements. All team members are in this channel. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 03_specification + topic: All around the spec discussions. It is ok to ask for support here. + purpose: All around the spec discussions. It is ok to ask for support here. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 04_tooling + topic: All around the specs tooling discussions. It is ok to ask for support here. + purpose: Chat about the AsyncAPI tooling + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 05_promotion-marketing + topic: Purpose of this channel is to help us with AsyncAPI promotion. Share your ideas for marketing and learn what we are working on at the moment. We use “channel” annotation here when we want to ask you to share our specific resources on different media. + purpose: Present launch plans for coordinated launches and to measure engagement and adoption + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 06_training + topic: All about trainings, workshops, courses, etc. — + purpose: All about trainings, workshops, courses, etc. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 07_events + topic: This is the place where we regroup and discuss organization of AsyncAPI-related events. This is also a place where you can always let others know what events are you involved in, where and when do you present a topic related to AsyncAPI. + purpose: This is the place where we regroup and discuss organization of AsyncAPI-related events. This is also a place where you can always let others know what events are you involved in, where and when do you present a topic related to AsyncAPI. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 08_jobs + topic: Looking for a job that will let you work on AsyncAPI? Let others know. Looking for AsyncAPI expert to join your company, post your offer here and also on the AsyncAPI website . + purpose: Looking for a job that will let you work on AsyncAPI? Let others know. Looking for AsyncAPI expert to join your company, post your offer here and also on the AsyncAPI website . + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 09_mentorships + topic: We participate in many different external programs, and also have our own that will evolve in next years. This is the place where we talk about these and coordinate. + purpose: We participate in many different external programs, and also have our own that will evolve in next years. This is the place where we talk about these and coordinate. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 10_watercooler + topic: Non-AsyncAPI topics. When you have a need to talk to someone “in person”, type “/zoom” in channel and start a meeting and let others know you are there. Talking to another human solves many problems. + purpose: A place for non-work-related flimflam, faffing, hodge-podge or jibber-jabber you'd prefer to keep out of more focused work-related channels. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 11_contributing + topic: Learn how to contribute. Ask contribution-related questions. Tell us what you want to learn through contribution and we will find you a good spot. Remember that you can contribute not only by pushing code. + purpose: Learn how to contribute. Share what you would like to learn and we will find for you a good place to start contributing + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 12_design + topic: Discuss design-related topics such as branding, design system, UI kit, and any other misc. design projects. Have a design request? Use this channel to propose and discuss your request! + purpose: Discuss design-related topics such as branding, design system, UI kit, and any other misc. design projects. Have a design request? Use this channel to propose and discuss your request! + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 13_docs + topic: null + purpose: ':bookmark_tabs: Discuss AsyncAPI Docs: Feel free to open issues for documentation requests and to share ideas/feedback on open issues. ' + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 14_accessibility + topic: Accessibility throughout the asyncAPI Initiative + purpose: Accessibility throughout the AsyncAPI Initiative + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 15_ambassadors + topic: null + purpose: All about the Ambassador Program. Feel free to participate! + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 16_news + topic: null + purpose: Share links to news you find about AsyncAPI (or related stuff) on the internet. Did you write something and want us to help you promote it? Use the <#CH44ZMJAZ|05_promotion-marketing> channel instead. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 17_bounty + topic: All about the AsyncAPI Bounty Program discussions. + purpose: This is the place where we discuss everything related to the Bounty Program. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 18_asyncapi-v3 + topic: This is the channel where we talk about AsyncAPI v3. From announcements, blogs, and livestreams. + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 19_coc + topic: null + purpose: Feel free to openly ask the Code of Conduct Committee if you have any questions. + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 93_bot-infra-alerts + topic: null + purpose: Alerts on infrastructure monitoring (New Relic by now) + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 94_bot-failing-ci + topic: null + purpose: When something wrong happens in CI and we configure Slack alerts - these should end up in this channel + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 95_bot-tsc-members-mentioned + topic: This channel is here to mainly help TSC members to get notifications other than email or GitHub notifications, every time TSC GitHub team is mentioned in issues, PRs and discussions + purpose: This channel is here to mainly help TSC members to get notifications other than email or GitHub notifications, every time TSC GitHub team is mentioned in issues, PRs and discussions + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 96_bot-stackoverflow-questions + topic: Stackoverflow questions tagged asyncapi from the RSS feed + purpose: Stackoverflow questions tagged `asyncapi` from the RSS feed + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 97_bot-github-new-issues-prs + topic: Bot sends notifications about every new issue and pull request in any AsyncAPI repository. + purpose: Notifications about all new issues and PR except of bots + is_private: false + is_archived: false + action_on_destroy: archive + +- name: 98_bot-github-releases + topic: Bot sends notifications about every new release in any AsyncAPI repository. + purpose: Notifications about new GitHub releases + is_private: false + is_archived: false + action_on_destroy: archive + +- name: glee-demos + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: gsoc2021-students-mentors-collaboration + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: help- + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: jsonschema + topic: 'Need help with JSON Schema? This channel is connected with the JSON Schema Slack workspace. Here you can talk with the JSON Schema community directly :raised_hands:' + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: libopenapi-speakeasy + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: linux + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: salemfr1100 + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: status-updates + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive + +- name: test-bot-public + topic: null + purpose: null + is_private: false + is_archived: false + action_on_destroy: archive diff --git a/.github/workflows/slack/groups/groups.tf b/.github/workflows/slack/groups/groups.tf new file mode 100644 index 000000000..9438fa7ec --- /dev/null +++ b/.github/workflows/slack/groups/groups.tf @@ -0,0 +1,74 @@ +terraform { + required_providers { + slack = { + source = "pablovarela/slack" + version = "~> 1.0" + } + } +} + +variable "wg_channels" { + description = "Map of working group channels" +} + +variable "data_sources" { + default = { + tsc_members_user_ids = [] + maintainers_user_ids = [] + repo_maintainers = {} + } + description = "Data sources for the slack groups from the users module" +} + +locals { + group_data = yamldecode(file("${path.module}/groups.yaml")) + groups = { + for group in local.group_data : group.name => { + name = group.name + handle = group.handle + description = group.description + users = lookup(group, "users", lookup(var.data_sources, lookup(group, "data_source", group.name), [])) + channels = lookup(group, "channels", []) + } + } +} + +resource "slack_usergroup" "groups" { + for_each = local.groups + name = each.value.name + handle = each.value.handle + description = each.value.description + users = each.value.users + channels = each.value.channels +} + +resource "slack_usergroup" "maintainer_repos" { + for_each = var.data_sources.repo_maintainers + name = "Maintainers of asyncapi/${each.key}" + handle = "maintainers_${each.key}" + description = "Maintainers for https://github.com/asyncapi/${each.key}" + users = each.value +} + +locals { + working_groups_data = yamldecode(file("${path.module}/../../../../WORKING_GROUPS.yaml")).working_groups + wg_groups = { + for wg_data in local.working_groups_data : wg_data.name => { + name = lookup(lookup(lookup(wg_data, "slack", {}), "group", {}), "name", wg_data.name) + description = lookup(lookup(lookup(wg_data, "slack", {}), "group", {}), "description", lookup(wg_data, "description", "")) + + # Handle will be the name of the group in lowercase and with spaces replaced by hyphens succeded by "wg-" + handle = lookup(lookup(lookup(wg_data, "slack", {}), "group", {}), "handle", "${replace(lower(wg_data.name), " ", "-")}-wg") + users = concat([for member in wg_data.chairpersons : member.slack], [for member in wg_data.members : member.slack]) + } + } +} + +resource "slack_usergroup" "wg_groups" { + for_each = local.wg_groups + name = each.value.name + handle = each.value.handle + description = each.value.description + users = each.value.users + channels = [var.wg_channels[each.value.name].id] +} \ No newline at end of file diff --git a/.github/workflows/slack/groups/groups.yaml b/.github/workflows/slack/groups/groups.yaml new file mode 100644 index 000000000..35a5695ef --- /dev/null +++ b/.github/workflows/slack/groups/groups.yaml @@ -0,0 +1,53 @@ +# - Groups: +# - name: (Required) The name of the user group. +# - handle: (Required) A name for the user group that is unique among channels, users, and user groups. +# - description: (Optional) A short description of the user group. +# - users: (Optional) A list of user IDs that are part of the user group. +# - data_source: (Optional) The data source to use for the user group. If users is not provided, the user group will be populated with users from the data source. +# - channels: (Optional) A list of channel IDs for channels that the user group will be in. + +# IMPORTANT: Once a user group is created it cannot be deleted. And an existing user group cannot be created again. +# Before adding them here please make sure to import them like this: +# terraform import slack_usergroup. + +- name: "TSC Members" + handle: "tsc" + description: "TSC members - https://www.asyncapi.com/community/tsc" + data_source: "tsc_members_user_ids" + +- name: "Maintainers" + handle: "maintainers" + description: "Maintainers" + data_source: "maintainers_user_ids" + +- name: "Studio" + handle: "studio" + description: "To notify all regular Studio contributors at once. If you don't contribute regularly but want to get notified too, please open a PR to get added." + users: + - "U01RWDD69PZ" + - "U0572R8J927" + - "U058PQFJPS4" + - "U01RVRD1TCL" + - "U01EB02BP7A" + - "U01TP1KJV1R" + - "U04STTQHV18" + - "U01N6AW5V5G" + - "U01SGCZMJKW" + channels: + - "CQVJXFNQL" + - "C02JW8DA0DC" + + +- name: "CoC Committee" + handle: "coc_committee" + description: "To notify the code of conduct team all at once when there is a question or anything related to them." + users: + - "U01RWDD69PZ" + - "U01J42QDSLU" + - "U03CNHGEUR1" + - "UN22ZTLHG" + - "U03CNJPMT7C" + - "U02AKC14WAJ" + channels: + - "C06FLH3AVSB" + - "C06CQCK03EJ" \ No newline at end of file diff --git a/.github/workflows/slack/slack.tf b/.github/workflows/slack/slack.tf new file mode 100644 index 000000000..98667ddc3 --- /dev/null +++ b/.github/workflows/slack/slack.tf @@ -0,0 +1,36 @@ +terraform { + required_providers { + slack = { + source = "pablovarela/slack" + version = "~> 1.0" + } + } + required_version = ">= 0.13" +} + +variable "slack_token" { + description = "The Slack API token with the channels:manage, channels:read, channels:write.invites, groups:read, groups:write, groups:write.invites, users:read scopes" + nullable = false + type = string +} + +provider "slack" { + token = var.slack_token +} + +module "users" { + source = "./users" +} + +module "channels" { + source = "./channels" + depends_on = [ module.users ] + data_sources = module.users.data_sources +} + +module "groups" { + source = "./groups" + depends_on = [ module.users, module.channels ] + data_sources = module.users.data_sources + wg_channels = module.channels.wg_channels +} \ No newline at end of file diff --git a/.github/workflows/slack/terraform.tfstate b/.github/workflows/slack/terraform.tfstate new file mode 100644 index 000000000..103451375 --- /dev/null +++ b/.github/workflows/slack/terraform.tfstate @@ -0,0 +1,999 @@ +{ + "version": 4, + "terraform_version": "1.7.1", + "serial": 40, + "lineage": "be714778-98f8-035d-1a6d-5aecc493dcb2", + "outputs": {}, + "resources": [ + { + "module": "module.channels", + "mode": "managed", + "type": "slack_conversation", + "name": "channels", + "provider": "provider[\"registry.terraform.io/pablovarela/slack\"]", + "instances": [ + { + "index_key": "01_introductions", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1622040350, + "creator": "UD698Q5LM", + "id": "C023GJWH33K", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "01_introductions", + "permanent_members": null, + "purpose": "Welcome to our AsyncAPI Slack! Take a moment to introduce yourself.", + "topic": "Welcome to our AsyncAPI Slack! Take a moment to introduce yourself." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "02_general", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1479472560, + "creator": "U34F2JRRS", + "id": "C34F2JV0U", + "is_archived": false, + "is_ext_shared": false, + "is_general": true, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "02_general", + "permanent_members": null, + "purpose": "This channel is for team-wide communication and announcements. All team members are in this channel.", + "topic": "Talk here if your topic is not only about the spec, nor tools but kinda mix and involves AsyncAPI :slightly_smiling_face:" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "03_specification", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1622040521, + "creator": "UD698Q5LM", + "id": "C0230UAM6R3", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "03_specification", + "permanent_members": null, + "purpose": "All around the spec discussions. It is ok to ask for support here.", + "topic": "All around the spec discussions. It is ok to ask for support here." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "04_tooling", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1574451424, + "creator": "U34F2JRRS", + "id": "CQVJXFNQL", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "04_tooling", + "permanent_members": null, + "purpose": "Chat about the AsyncAPI tooling", + "topic": "All around the specs tooling discussions. It is ok to ask for support here." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "05_promotion-marketing", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1553016525, + "creator": "UC3B0355Z", + "id": "CH44ZMJAZ", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "05_promotion-marketing", + "permanent_members": null, + "purpose": "Present launch plans for coordinated launches and to measure engagement and adoption", + "topic": "Purpose of this channel is to help us with AsyncAPI promotion. Share your ideas for marketing and learn what we are working on at the moment. We use “channel” annotation here when we want to ask you to share our specific resources on different media." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "06_training", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1620649432, + "creator": "U34F2JRRS", + "id": "C021E161QBV", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "06_training", + "permanent_members": null, + "purpose": "All about trainings, workshops, courses, etc.", + "topic": "All about trainings, workshops, courses, etc. — \u003chttps://github.com/asyncapi/training\u003e" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "07_events", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1622040979, + "creator": "UD698Q5LM", + "id": "C023A76SV2Q", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "07_events", + "permanent_members": null, + "purpose": "This is the place where we regroup and discuss organization of AsyncAPI-related events. This is also a place where you can always let others know what events are you involved in, where and when do you present a topic related to AsyncAPI.", + "topic": "This is the place where we regroup and discuss organization of AsyncAPI-related events. This is also a place where you can always let others know what events are you involved in, where and when do you present a topic related to AsyncAPI." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "08_jobs", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1622041069, + "creator": "UD698Q5LM", + "id": "C022P9CAMBR", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "08_jobs", + "permanent_members": null, + "purpose": "Looking for a job that will let you work on AsyncAPI? Let others know. Looking for AsyncAPI expert to join your company, post your offer here and also on the AsyncAPI website \u003chttps://www.asyncapi.com/jobs\u003e.", + "topic": "Looking for a job that will let you work on AsyncAPI? Let others know. Looking for AsyncAPI expert to join your company, post your offer here and also on the AsyncAPI website \u003chttps://www.asyncapi.com/jobs\u003e." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "09_mentorships", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1622041116, + "creator": "UD698Q5LM", + "id": "C023A7K5M3N", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "09_mentorships", + "permanent_members": null, + "purpose": "We participate in many different external programs, and also have our own that will evolve in next years. This is the place where we talk about these and coordinate.", + "topic": "We participate in many different external programs, and also have our own that will evolve in next years. This is the place where we talk about these and coordinate." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "10_watercooler", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1479472560, + "creator": "U34F2JRRS", + "id": "C34AUKWQK", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "10_watercooler", + "permanent_members": null, + "purpose": "A place for non-work-related flimflam, faffing, hodge-podge or jibber-jabber you'd prefer to keep out of more focused work-related channels.", + "topic": "Non-AsyncAPI topics. When you have a need to talk to someone “in person”, type “/zoom” in channel and start a meeting and let others know you are there. Talking to another human solves many problems." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "11_contributing", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1632379587, + "creator": "UD698Q5LM", + "id": "C02FK3YDPCL", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "11_contributing", + "permanent_members": null, + "purpose": "Learn how to contribute. Share what you would like to learn and we will find for you a good place to start contributing", + "topic": "Learn how to contribute. Ask contribution-related questions. Tell us what you want to learn through contribution and we will find you a good spot. Remember that you can contribute not only by pushing code." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "12_design", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1635256181, + "creator": "UD698Q5LM", + "id": "C02JW8DA0DC", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "12_design", + "permanent_members": null, + "purpose": "Discuss design-related topics such as branding, design system, UI kit, and any other misc. design projects. Have a design request? Use this channel to propose and discuss your request!", + "topic": "Discuss design-related topics such as branding, design system, UI kit, and any other misc. design projects. Have a design request? Use this channel to propose and discuss your request!" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "13_docs", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1639621854, + "creator": "U02AKC14WAJ", + "id": "C02QY9FMM18", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "13_docs", + "permanent_members": null, + "purpose": ":bookmark_tabs: Discuss AsyncAPI Docs: Feel free to open issues for documentation requests and to share ideas/feedback on open issues. \u003chttps://github.com/orgs/asyncapi/projects/8\u003e", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "14_accessibility", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1642713336, + "creator": "U02AKC14WAJ", + "id": "C02UV8CTT61", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "14_accessibility", + "permanent_members": null, + "purpose": "Accessibility throughout the AsyncAPI Initiative", + "topic": "Accessibility throughout the asyncAPI Initiative" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "15_ambassadors", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1678796519, + "creator": "U01J42QDSLU", + "id": "C04TRUTNPHB", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "15_ambassadors", + "permanent_members": null, + "purpose": "All about the Ambassador Program. Feel free to participate!", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "16_news", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1693300530, + "creator": "U34F2JRRS", + "id": "C05PWURSSP7", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "16_news", + "permanent_members": null, + "purpose": "Share links to news you find about AsyncAPI (or related stuff) on the internet. Did you write something and want us to help you promote it? Use the \u003c#CH44ZMJAZ|05_promotion-marketing\u003e channel instead.", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "17_bounty", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1696235939, + "creator": "U03CNJPMT7C", + "id": "C05UHTSEHE2", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "17_bounty", + "permanent_members": null, + "purpose": "This is the place where we discuss everything related to the Bounty Program.", + "topic": "All about the AsyncAPI Bounty Program discussions." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "18_asyncapi-v3", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1700755885, + "creator": "U03CNJPMT7C", + "id": "C066WFT906A", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "18_asyncapi-v3", + "permanent_members": null, + "purpose": "", + "topic": "This is the channel where we talk about AsyncAPI v3. From announcements, blogs, and livestreams." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "19_coc", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1706519672, + "creator": "U03CNJPMT7C", + "id": "C06FLH3AVSB", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "19_coc", + "permanent_members": null, + "purpose": "Feel free to openly ask the Code of Conduct Committee if you have any questions.", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "93_bot-infra-alerts", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1665663760, + "creator": "UN22ZTLHG", + "id": "C045Y33BZQX", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "93_bot-infra-alerts", + "permanent_members": null, + "purpose": "Alerts on infrastructure monitoring (New Relic by now)", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "94_bot-failing-ci", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1650439390, + "creator": "UD698Q5LM", + "id": "C03CHT8UFR7", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "94_bot-failing-ci", + "permanent_members": null, + "purpose": "When something wrong happens in CI and we configure Slack alerts - these should end up in this channel", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "95_bot-tsc-members-mentioned", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1644233870, + "creator": "UD698Q5LM", + "id": "C031UMXT63F", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "95_bot-tsc-members-mentioned", + "permanent_members": null, + "purpose": "This channel is here to mainly help TSC members to get notifications other than email or GitHub notifications, every time TSC GitHub team is mentioned in issues, PRs and discussions", + "topic": "This channel is here to mainly help TSC members to get notifications other than email or GitHub notifications, every time TSC GitHub team is mentioned in issues, PRs and discussions" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "96_bot-stackoverflow-questions", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1623665010, + "creator": "U6C2X4W1K", + "id": "C02544TFYJ0", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "96_bot-stackoverflow-questions", + "permanent_members": null, + "purpose": "Stackoverflow questions tagged `asyncapi` from the RSS feed", + "topic": "Stackoverflow questions tagged asyncapi from the RSS feed" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "97_bot-github-new-issues-prs", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1610383119, + "creator": "UD698Q5LM", + "id": "C01J06RL10X", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "97_bot-github-new-issues-prs", + "permanent_members": null, + "purpose": "Notifications about all new issues and PR except of bots", + "topic": "Bot sends notifications about every new issue and pull request in any AsyncAPI repository." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "98_bot-github-releases", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1610383083, + "creator": "UD698Q5LM", + "id": "C01JF00UGKC", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "98_bot-github-releases", + "permanent_members": null, + "purpose": "Notifications about new GitHub releases", + "topic": "Bot sends notifications about every new release in any AsyncAPI repository." + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "glee-demos", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1635694344, + "creator": "U34F2JRRS", + "id": "C02L1QCT1HP", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "glee-demos", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "gsoc2021-students-mentors-collaboration", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1622528565, + "creator": "U01CUAY035J", + "id": "C023H9V3ZLM", + "is_archived": false, + "is_ext_shared": true, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": true, + "name": "gsoc2021-students-mentors-collaboration", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "help-", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1640505133, + "creator": "U02SNQYK43A", + "id": "C02RJF383MM", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "help-", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "jsonschema", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1648200854, + "creator": "U5CJT43D2", + "id": "C038FTU4LQ6", + "is_archived": false, + "is_ext_shared": true, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": true, + "name": "jsonschema", + "permanent_members": null, + "purpose": "", + "topic": "Need help with JSON Schema? This channel is connected with the JSON Schema Slack workspace. Here you can talk with the JSON Schema community directly :raised_hands:" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "libopenapi-speakeasy", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1671028791, + "creator": "U03R0RBGA7N", + "id": "C04F6TQ40N7", + "is_archived": false, + "is_ext_shared": true, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": true, + "name": "libopenapi-speakeasy", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "linux", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1670708349, + "creator": "U04F18KAZEV", + "id": "C04EKM39P4M", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "linux", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "salemfr1100", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1682892720, + "creator": "U04RSMQHJ66", + "id": "C055JEMLGF7", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "salemfr1100", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "status-updates", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1709725751, + "creator": "U34F2JRRS", + "id": "C06N61ASV6X", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "status-updates", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "test-bot-public", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1683823890, + "creator": "U01RVRD1TCL", + "id": "C0579CUA7GD", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "test-bot-public", + "permanent_members": null, + "purpose": "", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + } + ] + }, + { + "module": "module.channels", + "mode": "managed", + "type": "slack_conversation", + "name": "wg_channels", + "provider": "provider[\"registry.terraform.io/pablovarela/slack\"]", + "instances": [ + { + "index_key": "Developer Experience", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1706786192, + "creator": "U34F2JRRS", + "id": "C06G92DN05D", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "wg-developer-experience", + "permanent_members": null, + "purpose": "The goal of this group is to empower AsyncAPI user journey trough intuitive onboarding, tools, and a frictionless experience.", + "topic": "Current Roadmap: \u003chttps://shapeit.app/projects/org/asyncapi/16/cycles/ceb40c9d?issue=I_kwDOLQFNzc5-xigF\u003e" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + }, + { + "index_key": "Essential Building Blocks", + "schema_version": 0, + "attributes": { + "action_on_destroy": null, + "action_on_update_permanent_members": null, + "adopt_existing_channel": null, + "created": 1712225888, + "creator": "U03CNJPMT7C", + "id": "C06SSB65QQJ", + "is_archived": false, + "is_ext_shared": false, + "is_general": false, + "is_org_shared": false, + "is_private": false, + "is_shared": false, + "name": "wg-essential-building-blocks", + "permanent_members": null, + "purpose": "The goal of the Essential Building Blocks Working Group is to provide fundamental building blocks that enable a similar developer experience across different languages. GitHub Project: \u003chttps://github.com/orgs/asyncapi/projects/44\u003e", + "topic": "" + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==" + } + ] + }, + { + "module": "module.groups", + "mode": "managed", + "type": "slack_usergroup", + "name": "groups", + "provider": "provider[\"registry.terraform.io/pablovarela/slack\"]", + "instances": [ + { + "index_key": "CoC Committee", + "schema_version": 0, + "attributes": { + "channels": [ + "C06CQCK03EJ", + "C06FLH3AVSB" + ], + "description": "To notify the code of conduct team all at once when there is a question or anything related to them.", + "handle": "coc_committee", + "id": "S06G3VCDTPU", + "name": "CoC Committee", + "users": [ + "U01J42QDSLU", + "U01RWDD69PZ", + "U02AKC14WAJ", + "U03CNHGEUR1", + "U03CNJPMT7C", + "UN22ZTLHG" + ] + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==", + "dependencies": [ + "module.channels.slack_conversation.channels", + "module.channels.slack_conversation.wg_channels" + ] + }, + { + "index_key": "Studio", + "schema_version": 0, + "attributes": { + "channels": [ + "C02JW8DA0DC", + "CQVJXFNQL" + ], + "description": "To notify all regular Studio contributors at once. If you don't contribute regularly but want to get notified too, ping Fran to get added.", + "handle": "studio", + "id": "S05D76QM92M", + "name": "Studio", + "users": [ + "U01EB02BP7A", + "U01N6AW5V5G", + "U01RVRD1TCL", + "U01RWDD69PZ", + "U01SGCZMJKW", + "U01TP1KJV1R", + "U04STTQHV18", + "U0572R8J927", + "U058PQFJPS4" + ] + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==", + "dependencies": [ + "module.channels.slack_conversation.channels", + "module.channels.slack_conversation.wg_channels" + ] + } + ] + }, + { + "module": "module.groups", + "mode": "managed", + "type": "slack_usergroup", + "name": "wg_groups", + "provider": "provider[\"registry.terraform.io/pablovarela/slack\"]", + "instances": [ + { + "index_key": "Developer Experience", + "schema_version": 0, + "attributes": { + "channels": [ + "C06G92DN05D" + ], + "description": "The Developer Experience Working Group", + "handle": "dx_wg", + "id": "S06T4ULNQL8", + "name": "Developer Experience Working Group", + "users": [ + "U0132LQU8C9", + "U01N6AW5V5G", + "U01RVRD1TCL", + "U01TP1KJV1R", + "U03CNHGEUR1", + "U04STTQHV18", + "U0572R8J927", + "U34F2JRRS", + "UTCN3ET4M" + ] + }, + "sensitive_attributes": [], + "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjAifQ==", + "dependencies": [ + "module.channels.slack_conversation.channels", + "module.channels.slack_conversation.wg_channels" + ] + } + ] + } + ], + "check_results": null +} diff --git a/.github/workflows/slack/users/users.tf b/.github/workflows/slack/users/users.tf new file mode 100644 index 000000000..4fa16dc9e --- /dev/null +++ b/.github/workflows/slack/users/users.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + slack = { + source = "pablovarela/slack" + version = "~> 1.0" + } + } +} + +locals { + maintainers_data = yamldecode(file("${path.root}/../../../MAINTAINERS.yaml")) + + # maintainers with isTscMember = true are added to the tsc_members group + tsc_members_data = [for maintainer in local.maintainers_data : maintainer if lookup(maintainer, "isTscMember", false) == true] + + # Make a map of repo maintainers with their slack user id with repo name as key + repos = setunion(flatten([for maintainer in local.maintainers_data : maintainer.repos])) + repo_maintainers = { + for repo in local.repos : repo => + [for maintainer in local.maintainers_data : maintainer.slack if contains(maintainer.repos, repo)] + } +} + +output "data_sources" { + value = { + maintainers_user_ids = [for maintainer in local.maintainers_data : maintainer.slack] + tsc_members_user_ids = [for tsc_member in local.tsc_members_data : tsc_member.slack] + repo_maintainers = local.repo_maintainers + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index b512c09d4..b0f0a309f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -node_modules \ No newline at end of file +node_modules +.terraform +*tfstate.backup +*.tfvars \ No newline at end of file diff --git a/TSC_MEMBERSHIP.md b/TSC_MEMBERSHIP.md index ef33c56d8..73373b9bd 100644 --- a/TSC_MEMBERSHIP.md +++ b/TSC_MEMBERSHIP.md @@ -49,3 +49,12 @@ Joining the TSC is something that you are allowed to do as a maintainer by defau See current [TSC members](https://www.asyncapi.com/community/tsc). +## How to reach out to the TSC + +There are several ways to reach out to the TSC members: + +* Join the [AsyncAPI Slack](https://www.asyncapi.com/slack-invite) and ping the `@tsc` group to ask questions or share your thoughts. +* Do a GitHub team mention `@asyncapi/tsc_members` in any issue, discussion or pull request. This will also send a message in the `95_bot-tsc-members-mentioned` channel in the Slack. + +> [!IMPORTANT] +> Please note that the TSC members are volunteers and may not be able to respond immediately. Please be patient and respectful. Also it will be helpful if there is as less spam as possible. For more information, please refer to the [Slack Etiquette](./slack-etiquette.md) document. diff --git a/WORKING_GROUPS.md b/WORKING_GROUPS.md index faee48724..bb7bb09ea 100644 --- a/WORKING_GROUPS.md +++ b/WORKING_GROUPS.md @@ -2,7 +2,10 @@ A Working Group is a group of people in our community who share a common interest beyond GitHub repositories. -A Working Group must have at least one of its members appointed as its chairperson. +A Working Group must have at least one of its members appointed as its **chairperson**. +The selection of the chairperson is done by the members of the group. Volunteers can be chairpersons, or the group can decide to elect one. The chairperson can also resign if they feel they can't fulfill their duties anymore. In this case, the group must elect a new chairperson if there is no other chairperson in the group. +The role of the chairperson is to facilitate the group meets its goals by removing blockers, ensuring the group works efficiently and is aligned with the AsyncAPI Roadmap. The chairperson is also responsible for running meetings effectively, ensuring that all members have a voice and that the group works in a transparent manner. +Multiple chairpersons can be elected if the working group members decide it's necessary. The way they share responsibilities is decided by the group. Anyone can create a Working Group. The only prerequisites are to have at least 3 founding members and the approval of the TSC (Technical Steering Committee). @@ -19,3 +22,14 @@ A Working Group must discuss ideas and solutions in public, and communicate thro It is recommended that the Working Group schedules meetings using the methods described at https://github.com/asyncapi/community/blob/master/MEETINGS_ORGANIZATION.md. Working Groups should be listed on the [AsyncAPI website](https://www.asyncapi.com), along with their description, goals, members, and anything the Working Group wants to include. + +### How to reach out to a Working Group + +There are several ways to reach out to a Working Group: + +- Join the [AsyncAPI Slack](https://www.asyncapi.com/slack-invite) and ping the working group's handle to ask questions or share your thoughts. The handle can be found in the [WORKING_GROUPS.yaml](./WORKING_GROUPS.yaml) file in the `slack.group.handle` field. Example: `@dx_wg`. +- Do a GitHub team mention in any issue, discussion, or pull request. The team handle can be found in the [WORKING_GROUPS.yaml](./WORKING_GROUPS.yaml) file in `github_team` field. Example: `developer_experience_wg`. +- Join the working group's channel on Slack. The channel name can be found in the [WORKING_GROUPS.yaml](./WORKING_GROUPS.yaml) file in the `slack.channel.handle` field. Example: `#wg-developer-experience`. + +> [!IMPORTANT] +> Please note that the Working Group members are volunteers and may not be able to respond immediately. Please be patient and respectful. Also, it will be helpful if there is as little spam as possible. For more information, please refer to the [Slack Etiquette](./slack-etiquette.md) document. \ No newline at end of file diff --git a/WORKING_GROUPS.yaml b/WORKING_GROUPS.yaml index 5d35c764e..af7919855 100644 --- a/WORKING_GROUPS.yaml +++ b/WORKING_GROUPS.yaml @@ -5,41 +5,160 @@ working_groups: # - name: Required. The name of the working group. # description: Required. Describe what this working group is about. - # chairperson: Required. GitHub handle of the chairperson. Example: @Barbanio. - # members: # Required to have at least 2 members who are not the same as the chairperson. - # - @fmvilas # GitHub handle of the member. - # slack_channel: # Required. The name of the Slack channel in the AsyncAPI workspace. Example: community_growth_wg + # chairpersons: # Required to have at least 1 chairperson. In case of multiple, and unless specified, the first one is the primary chairperson. + # - name: Fran Méndez # Required. Name of the chairperson. + # github: fmvilas # Required. GitHub handle of the chairperson without the @. + # slack: U34F2JRRS # Required. Slack user ID of the chairperson. + # members: # Required to have at least 2 members who are not the same as the chairperson(s). + # - name: Sergio Moya # Required. Name of the member. + # github: smoya # Required. GitHub handle of the member without the @. + # slack: UN22ZTLHG # Required. Slack user ID of the member. + # slack: + # channel: + # handle: # Required. The handle of the Slack channel in the AsyncAPI workspace. Recommended pattern: wg-. Example: wg-maintainers-growth. + # description: # Recommended. A brief description of the working group to be used in the Slack channel description. If not provided, the wg description will be used. + # topic: # Optional. The topic of the Slack channel. + # group: + # handle: # Optional. The handle of the Slack group in the AsyncAPI workspace. Recommended pattern: wg-. Example: maintainers-growth-wg. If not provided, the name of the wg will be used and transformed to follow the recommended pattern. The handle should be unique and not in use by a member, channel, or another group. + # name: # Optional. The name of the Slack group. (If not provided, the name of the group will be autogenerated based on the name of the wg). + # description: # Recommended. The description of the Slack group. (If not provided, the description of the wg will be used). # objectives: # Recommended. List of sentences outlining the objectives of the working group; or Link to a GitHub project, issue, or any other tool where the Working Group outlines their objectives. # - The AsyncAPI community grows sustainably. # roadmap_url: https://example.com/xyz # Recommended. Link to a GitHub project, issue, or any other tool where the Working Group outlines their roadmap. - # github_team: # Recommended. The GitHub team handle to tag all the working group members at once. Example: @asyncapi/community_growth_wg. + # github_team: # Recommended. The GitHub team handle to tag all the working group members at once. Example: maintainers_growth_wg, without @asyncapi/ prefix. - name: Essential Building Blocks description: The goal of the Essential Building Blocks Working Group is to provide fundamental building blocks that enable a similar developer experience across languages. - chairperson: @jonaslagoni + chairpersons: + - name: Jonas Lagoni + github: jonaslagoni + slack: UQ2ANBG1E members: - - @m-wild - - @lorenzsimon - - @VisualBean - - @Pakisan - - @Souvikns - - @jonaslagoni + - name: Michael Wildman + github: m-wild + slack: UNH2HT346 + - name: Lorenz Simon + github: lorenzsimon + slack: U06L7EQQSF2 + - name: Alex Wichmann + github: VisualBean + slack: U04C58GB8TF + - name: Pavel Bodiachevskii + github: pakisan + slack: U0132LQU8C9 + - name: Souvik De + github: Souvikns + slack: U01SGCZMJKW + slack: + channel: + handle: wg-essential-building-blocks + description: 'The goal of the Essential Building Blocks Working Group is to provide fundamental building blocks that enable a similar developer experience across different languages. GitHub Project: ' + group: + handle: essential-building-blocks-wg + description: Essential Building Blocks Working Group slack_channel: essential-building-blocks-wg roadmap_url: https://github.com/orgs/asyncapi/projects/44 - github_team: @asyncapi/essential_building_blocks_wg - okrs_url: https://github.com/orgs/asyncapi/projects/44 + github_team: essential_building_blocks_wg + objectives: + - https://github.com/orgs/asyncapi/projects/44 - name: Developer Experience description: The goal of this group is to empower AsyncAPI user journey trough intuitive onboarding, tools, and a frictionless experience. - chairperson: @Amzani + chairpersons: + - name: Samir Amzani + github: amzani + slack: U01N6AW5V5G members: - - @Pakisan - - @KhudaDad414 - - @ivangsa - - @peter-rr - - @Shurtu-gal - - @princerajpoot20 - - @Mayaleeeee - - @fmvilas - slack_channel: developer-experience-wg + - name: Pavel Bodiachevskii + github: pakisan + slack: U0132LQU8C9 + - name: Khuda Dad Nomani + github: KhudaDad414 + slack: U01RVRD1TCL + - name: Iván García Sainz-Aja + github: ivangsa + slack: UTCN3ET4M + - name: Pedro Ramos + github: peter-rr + slack: U01TP1KJV1R + - name: Ashish Padhy + github: Shurtu-gal + slack: U0572R8J927 + - name: Prince Rajpoot + github: princerajpoot20 + slack: U04STTQHV18 + - name: Aishat Muibudeen + github: Mayaleeeee + slack: U03CNHGEUR1 + - name: Fran Méndez + github: fmvilas + slack: U34F2JRRS + slack: + channel: + handle: wg-developer-experience + description: 'The goal of this group is to empower AsyncAPI user journey trough intuitive onboarding, tools, and a frictionless experience.' + topic: 'Current Roadmap: ' + group: + handle: dx_wg roadmap_url: https://shapeit.app/projects/org/asyncapi/16 - objectives: https://github.com/users/Amzani/projects/12/views/1 - github_team: @asyncapi/developer_experience_wg + objectives: + - https://github.com/users/Amzani/projects/12/views/1 + github_team: developer_experience_wg + - name: Maintainers Growth + description: The Maintainers Growth Working Group aims to help grow the number of maintainers at AsyncAPI. + chairpersons: + - name: Sergio Moya + github: smoya + slack: UN22ZTLHG + - name: Alejandra Quetzalli + github: alequetzalli + slack: U02AKC14WAJ + members: + - name: Elegbede Azeez + github: AceTheCreator + slack: U01RWDD69PZ + - name: Aishat Muibudeen + github: Mayaleeeee + slack: U03CNHGEUR1 + - name: Thulisile Sibanda + github: thulieblack + slack: U03CNJPMT7C + - name: Fran Méndez + github: fmvilas + slack: U34F2JRRS + slack: + channel: + handle: wg-maintainers-growth + description: This is the channel for the Maintainers Growth Working Group. + group: + handle: maintainers-growth-wg + description: Maintainers Growth Working Group + github_team: maintainers_growth_wg + - name: Conference Coordination + description: The goal of the group is to plan, manage, and create a seamless way to enhance the conference experience. + chairpersons: + - name: Thulisile Sibanda + github: thulieblack + slack: U03CNJPMT7C + members: + - name: Thulisile Sibanda + github: thulieblack + slack: U03CNJPMT7C + - name: Lukasz Gornicki + github: derberg + slack: UD698Q5LM + - name: Oluwabamikemi Kayode + github: iambami + slack: U070DE02VQX + - name: Aishat Muibudeen + github: Mayaleeeee + slack: U03CNHGEUR1 + - name: Azeez Elegbede + github: acethecreator + slack: U01RWDD69PZ + slack: + channel: + handle: wg-conference-coordination + description: 'The Conference Coordination Working Group aims to plan, manage, and create a seamless way to enhance the conference experience. GitHub Project: https://github.com/orgs/asyncapi/projects/43/views/2' + roadmap_url: https://github.com/orgs/asyncapi/projects/43/views/2 + objectives: + - https://github.com/orgs/asyncapi/projects/43/views/2 + github_team: conference_coordination_wg diff --git a/tweets/recurring-discuss-ideas/2024-05-01.tweet b/tweets/recurring-discuss-ideas/2024-05-01.tweet new file mode 100644 index 000000000..92b19fefe --- /dev/null +++ b/tweets/recurring-discuss-ideas/2024-05-01.tweet @@ -0,0 +1,5 @@ +Do you have some nice ideas for #AsyncAPI-related tools? Do you want to validate and share with the AsyncAPI community? + +Drop it 👇 and let us have an open discussion 🚀 + +https://github.com/asyncapi/community/discussions/categories/ideas \ No newline at end of file diff --git a/tweets/recurring-slack-link/2024-04-20.tweet b/tweets/recurring-slack-link/2024-04-20.tweet new file mode 100644 index 000000000..0bd3e8865 --- /dev/null +++ b/tweets/recurring-slack-link/2024-04-20.tweet @@ -0,0 +1,7 @@ +✨ Did you know #AsyncAPI is on Slack? ✨ + +Join our Slack workspace to chat with anyone from our Open-Source community! + +🔗 asyncapi.com/slack-invite + +Ask for help and help others too. 💪🏿💪🏽🦾 \ No newline at end of file diff --git a/tweets/recurring-slack-link/2024-04-27.tweet b/tweets/recurring-slack-link/2024-04-27.tweet new file mode 100644 index 000000000..0bd3e8865 --- /dev/null +++ b/tweets/recurring-slack-link/2024-04-27.tweet @@ -0,0 +1,7 @@ +✨ Did you know #AsyncAPI is on Slack? ✨ + +Join our Slack workspace to chat with anyone from our Open-Source community! + +🔗 asyncapi.com/slack-invite + +Ask for help and help others too. 💪🏿💪🏽🦾 \ No newline at end of file diff --git a/tweets/recurring-slack-link/2024-05-04.tweet b/tweets/recurring-slack-link/2024-05-04.tweet new file mode 100644 index 000000000..0bd3e8865 --- /dev/null +++ b/tweets/recurring-slack-link/2024-05-04.tweet @@ -0,0 +1,7 @@ +✨ Did you know #AsyncAPI is on Slack? ✨ + +Join our Slack workspace to chat with anyone from our Open-Source community! + +🔗 asyncapi.com/slack-invite + +Ask for help and help others too. 💪🏿💪🏽🦾 \ No newline at end of file diff --git a/tweets/recurring-slack-link/2024-05-11.tweet b/tweets/recurring-slack-link/2024-05-11.tweet new file mode 100644 index 000000000..0bd3e8865 --- /dev/null +++ b/tweets/recurring-slack-link/2024-05-11.tweet @@ -0,0 +1,7 @@ +✨ Did you know #AsyncAPI is on Slack? ✨ + +Join our Slack workspace to chat with anyone from our Open-Source community! + +🔗 asyncapi.com/slack-invite + +Ask for help and help others too. 💪🏿💪🏽🦾 \ No newline at end of file diff --git a/tweets/recurring-slack-link/2024-05-18.tweet b/tweets/recurring-slack-link/2024-05-18.tweet new file mode 100644 index 000000000..0bd3e8865 --- /dev/null +++ b/tweets/recurring-slack-link/2024-05-18.tweet @@ -0,0 +1,7 @@ +✨ Did you know #AsyncAPI is on Slack? ✨ + +Join our Slack workspace to chat with anyone from our Open-Source community! + +🔗 asyncapi.com/slack-invite + +Ask for help and help others too. 💪🏿💪🏽🦾 \ No newline at end of file diff --git a/tweets/recurring-slack-link/2024-05-25.tweet b/tweets/recurring-slack-link/2024-05-25.tweet new file mode 100644 index 000000000..0bd3e8865 --- /dev/null +++ b/tweets/recurring-slack-link/2024-05-25.tweet @@ -0,0 +1,7 @@ +✨ Did you know #AsyncAPI is on Slack? ✨ + +Join our Slack workspace to chat with anyone from our Open-Source community! + +🔗 asyncapi.com/slack-invite + +Ask for help and help others too. 💪🏿💪🏽🦾 \ No newline at end of file diff --git a/voting.md b/voting.md new file mode 100644 index 000000000..b2d3e71e0 --- /dev/null +++ b/voting.md @@ -0,0 +1,52 @@ +## Overview + +In the [search for the right governance model](https://www.asyncapi.com/blog/governance-motivation), we ended up defining a Technical Steering Committee (TSC) that can help make decisions related to the entire AsyncAPI Initiative and not only a specific repository. TSC voting is described in the official [Charter](https://github.com/asyncapi/community/blob/master/CHARTER.md#4-tsc-voting). + +To make the voting process easier with proper automation, we use [**Git Vote**](https://github.com/cncf/gitvote) bot. + +### Voting Location + +- Voting must only take place in the [community](https://github.com/asyncapi/community) repository. +- Voting automation works only with GitHub Issues and Pull Requests. + +The Discussions should only be used for initial discussion, brainstorming ideas, or seeking initial support. + +In the majority of cases, topics we vote on introduce new rules or ways of doing things. This implies that proper community documentation is needed for these topics. We recommend using Pull Requests instead of Issues to conduct voting on a topic, as it allows you to provide context and finalize documentation. + +### Voting Rules + +* Only votes from [TSC members](https://www.asyncapi.com/community/tsc) are counted. You are still encouraged to participate in voting, even if your vote is not binding. +* TSC members have at least 7 calendar days to vote. As a community, we did not set an exact voting deadline and only have a rule that you can translate into: "Just be nice and give people at least 7 days to get familiar with the topic so they can vote." Our automation is set for 4 weeks to take into account all possible limitations related to holidays and other events. +* TSC members can skip some votes, although, if you do not have an opinion, please participate with 👀 to indicate that you saw a vote but you have no opinion and abstain. There is one strict rule, though: if you do not participate in voting within three months, you will stop being a TSC member. It has nothing to do, though, with your maintainer responsibilities. +* The vote is completed when more than 50% of the voting is in favor. + +### Voting Process + +#### Start Voting + +1. The TSC member adds a `/vote` comment to an Issue or a Pull Request. +2. The Git Vote bot creates a comment with instructions on how the voting should be done. It is based on 👍🏼 , 👎🏼 and 👀 emojis. You can still put comments or suggestions. +3. The AsyncAPI bot adds a `vote` label, making it easier to extract information about voted topics and participation. + +#### Check Status + +1. Anyone can add a `/check-vote` comment to an Issue or a Pull Request. +2. The Git Vote bot creates a comment with an update on how many binding votes were provided. And how much the percentage is required to finish the voting process. + +### Cancel Voting + +1. The TSC member adds `/cancel-vote` comment to an Issue or a Pull Request. +2. The Git Vote bot creates a comment. +3. The AsyncAPI bot removes the `vote` label. + +### Finish Voting + +Voting cannot be concluded with a comment; it ends when more than half of the users with binding votes say yes or when the deadline passes. + +The Git Vote bot adds a comment that voting is completed. + +### Note + +* As per the [Charter](./CHARTER.md), a quorum is not needed. However, Git Vote has technical limitations, and a quorum should be reached. That's why we allocate 4 weeks for voting, and it's important to actively encourage participation to ensure that the quorum (where votes cast exceed 50% of eligible voters) is met. +* The abstain votes are included in the total number of votes; they are not removed. +* At present, Git Vote is enabled in the community repo only, and the Git Vote bot handles all voting processes. We will add Git Vote to other projects in the future.