diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 000000000000..649f7010f604 --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,426 @@ +{ + "projectName": "website", + "projectOwner": "asyncapi", + "repoType": "github", + "repoHost": "https://github.com", + "files": [ + "README.md" + ], + "imageSize": 100, + "commit": false, + "contributors": [ + { + "login": "fmvilas", + "name": "Fran MΓ©ndez", + "avatar_url": "https://avatars.githubusercontent.com/u/242119?v=4", + "profile": "http://www.fmvilas.com/", + "contributions": [ + "code", + "doc", + "bug", + "design", + "maintenance", + "infra", + "ideas", + "review", + "blog" + ] + }, + { + "login": "derberg", + "name": "Lukasz Gornicki", + "avatar_url": "https://avatars.githubusercontent.com/u/6995927?v=4", + "profile": "https://dev.to/derberg", + "contributions": [ + "code", + "doc", + "bug", + "design", + "maintenance", + "infra", + "ideas", + "review", + "blog" + ] + }, + { + "login": "magicmatatjahu", + "name": "Maciej UrbaΕ„czyk", + "avatar_url": "https://avatars.githubusercontent.com/u/20404945?v=4", + "profile": "https://github.com/magicmatatjahu", + "contributions": [ + "code", + "doc", + "bug", + "design", + "maintenance", + "infra", + "ideas", + "review", + "blog" + ] + }, + { + "login": "alequetzalli", + "name": "Alejandra Quetzalli ", + "avatar_url": "https://avatars.githubusercontent.com/u/19964402?v=4", + "profile": "https://github.com/alequetzalli", + "contributions": [ + "doc", + "review", + "talk" + ] + }, + { + "login": "aayushmau5", + "name": "Aayush Kumar Sahu", + "avatar_url": "https://avatars.githubusercontent.com/u/54525741?v=4", + "profile": "https://aayushmau5.github.io/", + "contributions": [ + "code", + "bug", + "design" + ] + }, + { + "login": "boyney123", + "name": "David Boyne", + "avatar_url": "https://avatars.githubusercontent.com/u/3268013?v=4", + "profile": "https://boyney.io/", + "contributions": [ + "code", + "design" + ] + }, + { + "login": "jessemenning", + "name": "Jesse Menning", + "avatar_url": "https://avatars.githubusercontent.com/u/62108913?v=4", + "profile": "https://github.com/jessemenning", + "contributions": [ + "blog" + ] + }, + { + "login": "dedoussis", + "name": "Dimitrios Dedoussis", + "avatar_url": "https://avatars.githubusercontent.com/u/24495755?v=4", + "profile": "https://dedouss.is/", + "contributions": [ + "blog" + ] + }, + { + "login": "jonaslagoni", + "name": "Jonas Lagoni", + "avatar_url": "https://avatars.githubusercontent.com/u/13396189?v=4", + "profile": "https://linkedin.com/in/jonaslagoni/", + "contributions": [ + "blog", + "code", + "review" + ] + }, + { + "login": "smoya", + "name": "Sergio Moya", + "avatar_url": "https://avatars.githubusercontent.com/u/1083296?v=4", + "profile": "https://github.com/smoya", + "contributions": [ + "code", + "blog", + "review" + ] + }, + { + "login": "bodograumann", + "name": "Bodo Graumann", + "avatar_url": "https://avatars.githubusercontent.com/u/1223583?v=4", + "profile": "https://github.com/bodograumann", + "contributions": [ + "doc" + ] + }, + { + "login": "damilolarandolph", + "name": "Damilola Randolph", + "avatar_url": "https://avatars.githubusercontent.com/u/43427949?v=4", + "profile": "https://damilolarandolph.com", + "contributions": [ + "code" + ] + }, + { + "login": "Barbanio", + "name": "Barbanio GonzΓ‘lez", + "avatar_url": "https://avatars.githubusercontent.com/u/77982319?v=4", + "profile": "https://github.com/Barbanio", + "contributions": [ + "blog", + "ideas" + ] + }, + { + "login": "hkaur008", + "name": "Hargun Kaur", + "avatar_url": "https://avatars.githubusercontent.com/u/56452820?v=4", + "profile": "https://github.com/hkaur008", + "contributions": [ + "code" + ] + }, + { + "login": "ceich", + "name": "Chris Eich", + "avatar_url": "https://avatars.githubusercontent.com/u/38611?v=4", + "profile": "https://github.com/ceich", + "contributions": [ + "review" + ] + }, + { + "login": "hpatoio", + "name": "Simone Fumagalli", + "avatar_url": "https://avatars.githubusercontent.com/u/249948?v=4", + "profile": "https://github.com/hpatoio", + "contributions": [ + "doc" + ] + }, + { + "login": "mcturco", + "name": "Missy Turco", + "avatar_url": "https://avatars.githubusercontent.com/u/60163079?v=4", + "profile": "https://melissaturco.com", + "contributions": [ + "code", + "design", + "ideas", + "review" + ] + }, + { + "login": "ritik307", + "name": "Ritik Rawal", + "avatar_url": "https://avatars.githubusercontent.com/u/22374829?v=4", + "profile": "https://ritik307.github.io/portfolio/", + "contributions": [ + "code" + ] + }, + { + "login": "akshatnema", + "name": "Akshat Nema", + "avatar_url": "https://avatars.githubusercontent.com/u/76521428?v=4", + "profile": "https://github.com/akshatnema", + "contributions": [ + "code" + ] + }, + { + "login": "BOLT04", + "name": "David Pereira", + "avatar_url": "https://avatars.githubusercontent.com/u/18630253?v=4", + "profile": "https://bolt04.github.io/react-ultimate-resume/", + "contributions": [ + "code", + "doc" + ] + }, + { + "login": "ron-debajyoti", + "name": "Debajyoti Halder", + "avatar_url": "https://avatars.githubusercontent.com/u/22571664?v=4", + "profile": "https://github.com/ron-debajyoti", + "contributions": [ + "code" + ] + }, + { + "login": "jaas666", + "name": "Juan A.", + "avatar_url": "https://avatars.githubusercontent.com/u/30204147?v=4", + "profile": "http://juanarce.me", + "contributions": [ + "code" + ] + }, + { + "login": "luphieanza", + "name": "Muhammad Rafly Andrianza", + "avatar_url": "https://avatars.githubusercontent.com/u/20577131?v=4", + "profile": "https://github.com/luphieanza", + "contributions": [ + "doc" + ] + }, + { + "login": "Harish-b-03", + "name": "Harish", + "avatar_url": "https://avatars.githubusercontent.com/u/69810789?v=4", + "profile": "https://github.com/Harish-b-03", + "contributions": [ + "code" + ] + }, + { + "login": "paulgoldsmith", + "name": "Paul Goldsmith", + "avatar_url": "https://avatars.githubusercontent.com/u/471550?v=4", + "profile": "https://github.com/paulgoldsmith", + "contributions": [ + "code", + "bug" + ] + }, + { + "login": "Dule-mart", + "name": "Tabah Baridule", + "avatar_url": "https://avatars.githubusercontent.com/u/33032530?v=4", + "profile": "http://www.twitter.com/dulemartins", + "contributions": [ + "doc" + ] + }, + { + "login": "starlightknown", + "name": "Karuna Tata", + "avatar_url": "https://avatars.githubusercontent.com/u/74637789?v=4", + "profile": "https://starlightknown.github.io/", + "contributions": [ + "a11y" + ] + }, + { + "login": "nibble0101", + "name": "Joseph Mawa", + "avatar_url": "https://avatars.githubusercontent.com/u/52580190?v=4", + "profile": "https://github.com/nibble0101", + "contributions": [ + "review" + ] + }, + { + "login": "aeworxet", + "name": "Viacheslav Turovskyi", + "avatar_url": "https://avatars.githubusercontent.com/u/16149591?v=4", + "profile": "https://github.com/aeworxet", + "contributions": [ + "doc", + "code" + ] + }, + { + "login": "hkosova", + "name": "Helen Kosova", + "avatar_url": "https://avatars.githubusercontent.com/u/8576823?v=4", + "profile": "https://www.linkedin.com/in/helen-kosova/", + "contributions": [ + "doc" + ] + }, + { + "login": "thulieblack", + "name": "V Thulisile Sibanda", + "avatar_url": "https://avatars.githubusercontent.com/u/66913810?v=4", + "profile": "https://linktr.ee/thulieblack", + "contributions": [ + "doc" + ] + }, + { + "login": "manavdesai27", + "name": "Manav Desai", + "avatar_url": "https://avatars.githubusercontent.com/u/74018438?v=4", + "profile": "https://github.com/manavdesai27", + "contributions": [ + "doc" + ] + }, + { + "login": "toukirkhan", + "name": "Mohd Toukir Khan", + "avatar_url": "https://avatars.githubusercontent.com/u/88899011?v=4", + "profile": "http://www.toukir.co", + "contributions": [ + "doc" + ] + }, + { + "login": "Annysah", + "name": "Anisat Akinbani", + "avatar_url": "https://avatars.githubusercontent.com/u/52763841?v=4", + "profile": "https://annysah.hashnode.dev", + "contributions": [ + "doc" + ] + }, + { + "login": "sambhavgupta0705", + "name": "sambhavgupta0705", + "avatar_url": "https://avatars.githubusercontent.com/u/81870866?v=4", + "profile": "https://github.com/sambhavgupta0705", + "contributions": [ + "code" + ] + }, + { + "login": "Ankitchaudharyy", + "name": "Ankit Chaudhary", + "avatar_url": "https://avatars.githubusercontent.com/u/46367738?v=4", + "profile": "https://github.com/Ankitchaudharyy", + "contributions": [ + "code" + ] + }, + { + "login": "Amzani", + "name": "samz", + "avatar_url": "https://avatars.githubusercontent.com/u/554438?v=4", + "profile": "https://github.com/Amzani", + "contributions": [ + "code" + ] + }, + { + "login": "BhaswatiRoy", + "name": "Bhaswati Roy ", + "avatar_url": "https://avatars.githubusercontent.com/u/78029145?v=4", + "profile": "https://bhaswatiroy.github.io/Bhaswati-Roy-Portfolio/", + "contributions": [ + "doc" + ] + }, + { + "login": "Mayaleeeee", + "name": "AISHAT MUIBUDEEN", + "avatar_url": "https://avatars.githubusercontent.com/u/105395613?v=4", + "profile": "https://www.behance.net/muibudeenaisha", + "contributions": [ + "design" + ] + }, + { + "login": "nawed2611", + "name": "Nawed Ali", + "avatar_url": "https://avatars.githubusercontent.com/u/83456083?v=4", + "profile": "https://nawedali.tech", + "contributions": [ + "code" + ] + }, + { + "login": "Olaleye-Blessing", + "name": "Olaleye Blessing", + "avatar_url": "https://avatars.githubusercontent.com/u/70102539?v=4", + "profile": "https://www.blessingolaleye.xyz/", + "contributions": [ + "code", + "a11y" + ] + } + ], + "contributorsPerLine": 7, + "skipCi": false, + "commitConvention": "angular" +} diff --git a/.editorconfig b/.editorconfig index da0310f513b6..967af902a8f0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,7 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true +quote_type = single [*.md] trim_trailing_whitespace = false \ No newline at end of file diff --git a/.env b/.env deleted file mode 100644 index 2aefb8b0f789..000000000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -DEPLOY_URL=http://localhost:8080 \ No newline at end of file diff --git a/.github/workflows/add-good-first-issue-labels.yml b/.github/workflows/add-good-first-issue-labels.yml new file mode 100644 index 000000000000..2ae3a056ae17 --- /dev/null +++ b/.github/workflows/add-good-first-issue-labels.yml @@ -0,0 +1,71 @@ +# This workflow is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +# Purpose of this workflow is to enable anyone to label issue with 'Good First Issue' and 'area/*' with a single command. +name: Add 'Good First Issue' and 'area/*' labels # if proper comment added + +on: + issue_comment: + types: + - created + +jobs: + add-labels: + if: ${{(!github.event.issue.pull_request && github.event.issue.state != 'closed' && github.actor != 'asyncapi-bot') && (contains(github.event.comment.body, '/good-first-issue') || contains(github.event.comment.body, '/gfi' ))}} + runs-on: ubuntu-latest + steps: + - name: Add label + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + const areas = ['javascript', 'typescript', 'java' , 'go', 'docs', 'ci-cd', 'design']; + const words = context.payload.comment.body.trim().split(" "); + const areaIndex = words.findIndex((word)=> word === '/gfi' || word === '/good-first-issue') + 1 + let area = words[areaIndex]; + switch(area){ + case 'ts': + area = 'typescript'; + break; + case 'js': + area = 'javascript'; + break; + case 'markdown': + area = 'docs'; + break; + } + if(!areas.includes(area)){ + const message = `Hey @${context.payload.sender.login}, your message doesn't follow the requirements, you can try \`/help\`.` + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: message + }) + } else { + + // remove area if there is any before adding new labels. + const currentLabels = (await github.rest.issues.listLabelsOnIssue({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + })).data.map(label => label.name); + + const shouldBeRemoved = currentLabels.filter(label => (label.startsWith('area/') && !label.endsWith(area))); + shouldBeRemoved.forEach(label => { + github.rest.issues.deleteLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: label, + }); + }); + + // Add new labels. + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['good first issue', `area/${area}`] + }); + } diff --git a/.github/workflows/automerge-for-humans-add-ready-to-merge-or-do-not-merge-label.yml b/.github/workflows/automerge-for-humans-add-ready-to-merge-or-do-not-merge-label.yml new file mode 100644 index 000000000000..66606fc17aa3 --- /dev/null +++ b/.github/workflows/automerge-for-humans-add-ready-to-merge-or-do-not-merge-label.yml @@ -0,0 +1,110 @@ +# This workflow is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +# Purpose of this workflow is to enable anyone to label PR with the following labels: +# `ready-to-merge` and `do-not-merge` labels to get stuff merged or blocked from merging +# `autoupdate` to keep a branch up-to-date with the target branch + +name: Label PRs # if proper comment added + +on: + issue_comment: + types: + - created + +jobs: + add-ready-to-merge-label: + if: > + github.event.issue.pull_request && + github.event.issue.state != 'closed' && + github.actor != 'asyncapi-bot' && + ( + contains(github.event.comment.body, '/ready-to-merge') || + contains(github.event.comment.body, '/rtm' ) + ) + + runs-on: ubuntu-latest + steps: + - name: Add ready-to-merge label + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + const prDetailsUrl = context.payload.issue.pull_request.url; + const { data: pull } = await github.request(prDetailsUrl); + const { draft: isDraft} = pull; + if(!isDraft) { + console.log('adding ready-to-merge label...'); + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['ready-to-merge'] + }) + } + + const { data: comparison } = + await github.rest.repos.compareCommitsWithBasehead({ + owner: pull.head.repo.owner.login, + repo: pull.head.repo.name, + basehead: `${pull.base.label}...${pull.head.label}`, + }); + if (comparison.behind_by !== 0 && pull.mergeable_state === 'behind') { + console.log(`This branch is behind the target by ${comparison.behind_by} commits`) + console.log('adding out-of-date comment...'); + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `Hello, @${{ github.actor }}! πŸ‘‹πŸΌ + This PR is not up to date with the base branch and can't be merged. + Please update your branch manually with the latest version of the base branch. + PRO-TIP: Add a comment to your PR with the text: \`/au\` or \`/autoupdate\` and our bot will take care of updating the branch in the future. The only requirement for this to work is to enable [Allow edits from maintainers](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) option in your PR. + Thanks πŸ˜„` + }) + } + + add-do-not-merge-label: + if: > + github.event.issue.pull_request && + github.event.issue.state != 'closed' && + github.actor != 'asyncapi-bot' && + ( + contains(github.event.comment.body, '/do-not-merge') || + contains(github.event.comment.body, '/dnm' ) + ) + runs-on: ubuntu-latest + steps: + - name: Add do-not-merge label + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['do-not-merge'] + }) + add-autoupdate-label: + if: > + github.event.issue.pull_request && + github.event.issue.state != 'closed' && + github.actor != 'asyncapi-bot' && + ( + contains(github.event.comment.body, '/autoupdate') || + contains(github.event.comment.body, '/au' ) + ) + runs-on: ubuntu-latest + steps: + - name: Add autoupdate label + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['autoupdate'] + }) diff --git a/.github/workflows/automerge-for-humans-merging.yml b/.github/workflows/automerge-for-humans-merging.yml new file mode 100644 index 000000000000..9ba0be90bd7b --- /dev/null +++ b/.github/workflows/automerge-for-humans-merging.yml @@ -0,0 +1,55 @@ +# This workflow is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +# Purpose of this workflow is to allow people to merge PR without a need of maintainer doing it. If all checks are in place (including maintainers approval) - JUST MERGE IT! +name: Automerge For Humans + +on: + pull_request_target: + types: + - labeled + - unlabeled + - synchronize + - opened + - edited + - ready_for_review + - reopened + - unlocked + +jobs: + automerge-for-humans: + if: github.event.pull_request.draft == false && (github.event.pull_request.user.login != 'asyncapi-bot' || github.event.pull_request.user.login != 'dependabot[bot]' || github.event.pull_request.user.login != 'dependabot-preview[bot]') #it runs only if PR actor is not a bot, at least not a bot that we know + runs-on: ubuntu-latest + steps: + - name: Get list of authors + uses: sergeysova/jq-action@v2 + id: authors + with: + # This cmd does following (line by line): + # 1. CURL querying the list of commits of the current PR via GH API. Why? Because the current event payload does not carry info about the commits. + # 2. Iterates over the previous returned payload, and creates an array with the filtered results (see below) so we can work wit it later. An example of payload can be found in https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#webhook-payload-example-34. + # 3. Grabs the data we need for adding the `Co-authored-by: ...` lines later and puts it into objects to be used later on. + # 4. Filters the results by excluding the current PR sender. We don't need to add it as co-author since is the PR creator and it will become by default the main author. + # 5. Removes repeated authors (authors can have more than one commit in the PR). + # 6. Builds the `Co-authored-by: ...` lines with actual info. + # 7. Transforms the array into plain text. Thanks to this, the actual stdout of this step can be used by the next Workflow step (wich is basically the automerge). + cmd: | + curl -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GH_TOKEN }}" "${{github.event.pull_request._links.commits.href}}?per_page=100" | + jq -r '[.[] + | {name: .commit.author.name, email: .commit.author.email, login: .author.login}] + | map(select(.login != "${{github.event.pull_request.user.login}}")) + | unique + | map("Co-authored-by: " + .name + " <" + .email + ">") + | join("\n")' + multiline: true + - name: Automerge PR + uses: pascalgn/automerge-action@22948e0bc22f0aa673800da838595a3e7347e584 #v0.15.6 https://github.com/pascalgn/automerge-action/releases/tag/v0.15.6 + env: + GITHUB_TOKEN: "${{ secrets.GH_TOKEN }}" + MERGE_LABELS: "!do-not-merge,ready-to-merge" + MERGE_METHOD: "squash" + # Using the output of the previous step (`Co-authored-by: ...` lines) as commit description. + # Important to keep 2 empty lines as https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors#creating-co-authored-commits-on-the-command-line mentions + MERGE_COMMIT_MESSAGE: "{pullRequest.title} (#{pullRequest.number})\n\n\n${{ steps.authors.outputs.value }}" + MERGE_RETRIES: "20" + MERGE_RETRY_SLEEP: "30000" diff --git a/.github/workflows/automerge-for-humans-remove-ready-to-merge-label-on-edit.yml b/.github/workflows/automerge-for-humans-remove-ready-to-merge-label-on-edit.yml new file mode 100644 index 000000000000..00e7f99356dc --- /dev/null +++ b/.github/workflows/automerge-for-humans-remove-ready-to-merge-label-on-edit.yml @@ -0,0 +1,32 @@ +# This workflow is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +# Defence from evil contributor that after adding `ready-to-merge` all suddenly makes evil commit or evil change in PR title +# Label is removed once above action is detected +name: Remove ready-to-merge label + +on: + pull_request_target: + types: + - synchronize + - edited + +jobs: + remove-ready-label: + runs-on: ubuntu-latest + steps: + - name: Remove label + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + const labelToRemove = 'ready-to-merge'; + const labels = context.payload.pull_request.labels; + const isLabelPresent = labels.some(label => label.name === labelToRemove) + if(!isLabelPresent) return; + github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: labelToRemove + }) diff --git a/.github/workflows/automerge-orphans.yml b/.github/workflows/automerge-orphans.yml index d712c13d03fe..a177685357be 100644 --- a/.github/workflows/automerge-orphans.yml +++ b/.github/workflows/automerge-orphans.yml @@ -1,5 +1,5 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo name: 'Notify on failing automerge' @@ -9,25 +9,27 @@ on: jobs: identify-orphans: + if: startsWith(github.repository, 'asyncapi/') name: Find orphans and notify runs-on: ubuntu-latest steps: + - name: Checkout repository + uses: actions/checkout@v3 - name: Get list of orphans - uses: actions/github-script@v3 + uses: actions/github-script@v6 id: orphans with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const query = `query($owner:String!, $name:String!) { repository(owner:$owner, name:$name){ - pullRequests(first: 100){ + pullRequests(first: 100, states: OPEN){ nodes{ title url author { resourcePath } - state } } } @@ -38,7 +40,7 @@ jobs: }; const { repository: { pullRequests: { nodes } } } = await github.graphql(query, variables); - let orphans = nodes.filter((pr)=> pr.state === 'OPEN' && (pr.author.resourcePath === '/asyncapi-bot' || pr.author.resourcePath === '/apps/dependabot')) + let orphans = nodes.filter( (pr) => pr.author.resourcePath === '/asyncapi-bot' || pr.author.resourcePath === '/apps/dependabot') if (orphans.length) { core.setOutput('found', 'true'); @@ -50,15 +52,15 @@ jobs: } - if: steps.orphans.outputs.found == 'true' name: Convert markdown to slack markdown - uses: LoveToKnow/slackify-markdown-action@v1.0.0 + uses: asyncapi/.github/.github/actions/slackify-markdown@master id: issuemarkdown with: - text: "-> [${{steps.orphans.outputs.title}}](${{steps.orphans.outputs.url}})" + markdown: "-> [${{steps.orphans.outputs.title}}](${{steps.orphans.outputs.url}})" - if: steps.orphans.outputs.found == 'true' name: Send info about orphan to slack uses: rtCamp/action-slack-notify@v2 env: - SLACK_WEBHOOK: ${{secrets.SLACK_GITHUB_NEWISSUEPR}} + SLACK_WEBHOOK: ${{secrets.SLACK_CI_FAIL_NOTIFY}} SLACK_TITLE: 🚨 Not merged PR that should be automerged 🚨 SLACK_MESSAGE: ${{steps.issuemarkdown.outputs.text}} MSG_MINIMAL: true \ No newline at end of file diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index d9685646390f..9253675cd666 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -1,51 +1,52 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo. -name: Automerge release bump PR +name: Automerge PRs from bots on: - pull_request: + pull_request_target: types: - - labeled - - unlabeled - - synchronize - opened - - edited - - ready_for_review - - reopened - - unlocked - pull_request_review: - types: - - submitted - check_suite: - types: - - completed - status: {} - -jobs: + - synchronize - autoapprove: - if: github.event.pull_request.draft == false +jobs: + autoapprove-for-bot: + name: Autoapprove PR comming from a bot + if: > + contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]"]'), github.event.pull_request.user.login) && + contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]"]'), github.actor) && + !contains(github.event.pull_request.labels.*.name, 'released') runs-on: ubuntu-latest steps: - name: Autoapproving - uses: hmarr/auto-approve-action@v2.0.0 - if: github.actor == 'asyncapi-bot' || github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' + uses: hmarr/auto-approve-action@44888193675f29a83e04faf4002fa8c0b537b1e4 # v3.2.1 is used https://github.com/hmarr/auto-approve-action/releases/tag/v3.2.1 + with: + github-token: "${{ secrets.GH_TOKEN_BOT_EVE }}" + + - name: Label autoapproved + uses: actions/github-script@v6 with: - github-token: "${{ secrets.GITHUB_TOKEN }}" + github-token: ${{ secrets.GH_TOKEN }} + script: | + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['autoapproved', 'autoupdate'] + }) - automerge: - needs: [autoapprove] + automerge-for-bot: + name: Automerge PR autoapproved by a bot + needs: [autoapprove-for-bot] runs-on: ubuntu-latest steps: - name: Automerging - uses: pascalgn/automerge-action@v0.7.5 - if: github.actor == 'asyncapi-bot' || github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' + uses: pascalgn/automerge-action@22948e0bc22f0aa673800da838595a3e7347e584 #v0.15.6 https://github.com/pascalgn/automerge-action/releases/tag/v0.15.6 env: GITHUB_TOKEN: "${{ secrets.GH_TOKEN }}" GITHUB_LOGIN: asyncapi-bot MERGE_LABELS: "" MERGE_METHOD: "squash" - MERGE_COMMIT_MESSAGE: "pull-request-title" + MERGE_COMMIT_MESSAGE: "{pullRequest.title} (#{pullRequest.number})" MERGE_RETRIES: "20" - MERGE_RETRY_SLEEP: "20000" \ No newline at end of file + MERGE_RETRY_SLEEP: "30000" diff --git a/.github/workflows/autoupdate.yml b/.github/workflows/autoupdate.yml new file mode 100644 index 000000000000..ad8e0198f023 --- /dev/null +++ b/.github/workflows/autoupdate.yml @@ -0,0 +1,34 @@ +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +# This workflow is designed to work with: +# - autoapprove and automerge workflows for dependabot and asyncapibot. +# - special release branches that we from time to time create in upstream repos. If we open up PRs for them from the very beginning of the release, the release branch will constantly update with new things from the destination branch they are opened against + +# It uses GitHub Action that auto-updates pull requests branches, whenever changes are pushed to their destination branch. +# Autoupdating to latest destination branch works only in the context of upstream repo and not forks + +name: autoupdate + +on: + push: + branches-ignore: + - 'version-bump/**' + - 'dependabot/**' + - 'bot/**' + - 'all-contributors/**' + +jobs: + autoupdate-for-bot: + if: startsWith(github.repository, 'asyncapi/') + name: Autoupdate autoapproved PR created in the upstream + runs-on: ubuntu-latest + steps: + - name: Autoupdating + uses: docker://chinthakagodawita/autoupdate-action:v1 + env: + GITHUB_TOKEN: '${{ secrets.GH_TOKEN_BOT_EVE }}' + PR_FILTER: "labelled" + PR_LABELS: "autoupdate" + PR_READY_STATE: "ready_for_review" + MERGE_CONFLICT_ACTION: "ignore" diff --git a/.github/workflows/help-command.yml b/.github/workflows/help-command.yml new file mode 100644 index 000000000000..f4955c221630 --- /dev/null +++ b/.github/workflows/help-command.yml @@ -0,0 +1,60 @@ +# This workflow is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +name: Create help comment + +on: + issue_comment: + types: + - created + +jobs: + create_help_comment_pr: + if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/help') && github.actor != 'asyncapi-bot' }} + runs-on: ubuntu-latest + steps: + - name: Add comment to PR + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + //Yes to add comment to PR the same endpoint is use that we use to create a comment in issue + //For more details http://developer.github.com/v3/issues/comments/ + //Also proved by this action https://github.com/actions-ecosystem/action-create-comment/blob/main/src/main.ts + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `Hello, @${{ github.actor }}! πŸ‘‹πŸΌ + + I'm Genie from the magic lamp. Looks like somebody needs a hand! πŸ†˜ + + At the moment the following comments are supported in pull requests: + + - `/ready-to-merge` or `/rtm` - This comment will trigger automerge of PR in case all required checks are green, approvals in place and do-not-merge label is not added + - `/do-not-merge` or `/dnm` - This comment will block automerging even if all conditions are met and ready-to-merge label is added + - `/autoupdate` or `/au` - This comment will add `autoupdate` label to the PR and keeps your PR up-to-date to the target branch's future changes. Unless there is a merge conflict or it is a draft PR.` + }) + + create_help_comment_issue: + if: ${{ !github.event.issue.pull_request && contains(github.event.comment.body, '/help') && github.actor != 'asyncapi-bot' }} + runs-on: ubuntu-latest + steps: + - name: Add comment to Issue + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GH_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `Hello, @${{ github.actor }}! πŸ‘‹πŸΌ + + I'm Genie from the magic lamp. Looks like somebody needs a hand! πŸ†˜ + + At the moment the following comments are supported in issues: + + - `/good-first-issue {js | ts | java | go | docs | design | ci-cd} ` or `/gfi {js | ts | java | go | docs | design | ci-cd} ` - label an issue as a `good first issue`. + example: `/gfi js` or `/good-first-issue ci-cd` + }) diff --git a/.github/workflows/if-nodejs-pr-testing.yml b/.github/workflows/if-nodejs-pr-testing.yml deleted file mode 100644 index b39bfea427fb..000000000000 --- a/.github/workflows/if-nodejs-pr-testing.yml +++ /dev/null @@ -1,41 +0,0 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo -#It does magic only if there is package.json file in the root of the project -name: PR testing - if Node project - -on: - pull_request: - types: [opened, reopened, synchronize, ready_for_review] - -jobs: - test: - if: github.event.pull_request.draft == false - name: ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Check if Node.js project and has package.json - id: packagejson - run: test -e ./package.json && echo "::set-output name=exists::true" || echo "::set-output name=exists::false" - shell: bash - - if: steps.packagejson.outputs.exists == 'true' - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: 14 - - if: steps.packagejson.outputs.exists == 'true' - name: Install dependencies - run: npm install --loglevel verbose - - if: steps.packagejson.outputs.exists == 'true' - name: Test - run: npm test - - if: steps.packagejson.outputs.exists == 'true' - name: Run linter - run: npm run lint - - if: steps.packagejson.outputs.exists == 'true' - name: Run release assets generation to make sure PR does not break it - run: npm run generate:assets diff --git a/.github/workflows/if-nodejs-release.yml b/.github/workflows/if-nodejs-release.yml deleted file mode 100644 index 7da5645aad9d..000000000000 --- a/.github/workflows/if-nodejs-release.yml +++ /dev/null @@ -1,66 +0,0 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo -#It does magic only if there is package.json file in the root of the project -name: Release - if Node project - -on: - push: - branches: - - master - -jobs: - - test: - name: Test on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Check if Node.js project and has package.json - id: packagejson - run: test -e ./package.json && echo "::set-output name=exists::true" || echo "::set-output name=exists::false" - shell: bash - - if: steps.packagejson.outputs.exists == 'true' - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: 14 - - if: steps.packagejson.outputs.exists == 'true' - name: Install dependencies - run: npm install - - if: steps.packagejson.outputs.exists == 'true' - name: Run test - run: npm test - - release: - needs: test - name: Publish to NPM and GitHub - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Check if Node.js project and has package.json - id: packagejson - run: test -e ./package.json && echo "::set-output name=exists::true" || echo "::set-output name=exists::false" - - if: steps.packagejson.outputs.exists == 'true' - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: 14 - - if: steps.packagejson.outputs.exists == 'true' - name: Install dependencies - run: npm install - - if: steps.packagejson.outputs.exists == 'true' - name: Release to NPM and GitHub - id: release - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - GIT_AUTHOR_NAME: asyncapi-bot - GIT_AUTHOR_EMAIL: info@asyncapi.io - GIT_COMMITTER_NAME: asyncapi-bot - GIT_COMMITTER_EMAIL: info@asyncapi.io - run: npm run release \ No newline at end of file diff --git a/.github/workflows/if-nodejs-version-bump.yml b/.github/workflows/if-nodejs-version-bump.yml deleted file mode 100644 index 34d57df82b15..000000000000 --- a/.github/workflows/if-nodejs-version-bump.yml +++ /dev/null @@ -1,45 +0,0 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo -#It does magic only if there is package.json file in the root of the project -name: Version bump - if Node.js project - -on: - release: - types: - - published - -jobs: - version_bump: - name: Generate assets and bump - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v2 - with: - ref: master - - name: Check if Node.js project and has package.json - id: packagejson - run: test -e ./package.json && echo "::set-output name=exists::true" || echo "::set-output name=exists::false" - - if: steps.packagejson.outputs.exists == 'true' - name: Install dependencies - run: npm install - - if: steps.packagejson.outputs.exists == 'true' - name: Assets generation - run: npm run generate:assets - - if: steps.packagejson.outputs.exists == 'true' - name: Bump version in package.json - # There is no need to substract "v" from the tag as version script handles it - # When adding "bump:version" script in package.json, make sure no tags are added by default (--no-git-tag-version) as they are already added by release workflow - # When adding "bump:version" script in package.json, make sure --allow-same-version is set in case someone forgot and updated package.json manually and we want to avoide this action to fail and raise confusion - run: VERSION=${{github.event.release.tag_name}} npm run bump:version - - if: steps.packagejson.outputs.exists == 'true' - name: Create Pull Request with updated asset files including package.json - uses: peter-evans/create-pull-request@v3 - with: - token: ${{ secrets.GH_TOKEN }} - commit-message: 'chore(release): ${{github.event.release.tag_name}}' - committer: asyncapi-bot - author: asyncapi-bot - title: 'chore(release): ${{github.event.release.tag_name}}' - body: 'Version bump in package.json for release [${{github.event.release.tag_name}}](${{github.event.release.html_url}})' - branch: version-bump/${{github.event.release.tag_name}} \ No newline at end of file diff --git a/.github/workflows/issues-prs-notifications.yml b/.github/workflows/issues-prs-notifications.yml index 8577db6fc312..78ebe960113c 100644 --- a/.github/workflows/issues-prs-notifications.yml +++ b/.github/workflows/issues-prs-notifications.yml @@ -1,49 +1,76 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +# This action notifies community on slack whenever there is a new issue, PR or discussion started in given repository name: Notify slack on: - issues: types: [opened, reopened] pull_request_target: types: [opened, reopened, ready_for_review] + discussion: + types: [created] + jobs: + issue: + if: github.event_name == 'issues' && github.actor != 'asyncapi-bot' && github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' + name: Notify slack on every new issue + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Convert markdown to slack markdown for issue + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: issuemarkdown + with: + markdown: "[${{github.event.issue.title}}](${{github.event.issue.html_url}}) \n ${{github.event.issue.body}}" + - name: Send info about issue + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_GITHUB_NEWISSUEPR}} + SLACK_TITLE: πŸ› New Issue in ${{github.repository}} πŸ› + SLACK_MESSAGE: ${{steps.issuemarkdown.outputs.text}} + MSG_MINIMAL: true - issue: - if: github.event_name == 'issues' && github.actor != 'asyncapi-bot' && github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' - name: On every new issue - runs-on: ubuntu-latest - steps: - - name: Convert markdown to slack markdown for issue - uses: LoveToKnow/slackify-markdown-action@v1.0.0 - id: issuemarkdown - with: - text: "[${{github.event.issue.title}}](${{github.event.issue.html_url}}) \n ${{github.event.issue.body}}" - - name: Send info about issue - uses: rtCamp/action-slack-notify@v2 - env: - SLACK_WEBHOOK: ${{secrets.SLACK_GITHUB_NEWISSUEPR}} - SLACK_TITLE: πŸ› New Issue πŸ› - SLACK_MESSAGE: ${{steps.issuemarkdown.outputs.text}} - MSG_MINIMAL: true + pull_request: + if: github.event_name == 'pull_request_target' && github.actor != 'asyncapi-bot' && github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' + name: Notify slack on every new pull request + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Convert markdown to slack markdown for pull request + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: prmarkdown + with: + markdown: "[${{github.event.pull_request.title}}](${{github.event.pull_request.html_url}}) \n ${{github.event.pull_request.body}}" + - name: Send info about pull request + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_GITHUB_NEWISSUEPR}} + SLACK_TITLE: πŸ’ͺ New Pull Request in ${{github.repository}} πŸ’ͺ + SLACK_MESSAGE: ${{steps.prmarkdown.outputs.text}} + MSG_MINIMAL: true - pull_request: - if: github.event_name == 'pull_request_target' && github.actor != 'asyncapi-bot' && github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' - name: On every new pull request - runs-on: ubuntu-latest - steps: - - name: Convert markdown to slack markdown for pull request - uses: LoveToKnow/slackify-markdown-action@v1.0.0 - id: prmarkdown - with: - text: "[${{github.event.pull_request.title}}](${{github.event.pull_request.html_url}}) \n ${{github.event.pull_request.body}}" - - name: Send info about pull request - uses: rtCamp/action-slack-notify@v2 - env: - SLACK_WEBHOOK: ${{secrets.SLACK_GITHUB_NEWISSUEPR}} - SLACK_TITLE: πŸ’ͺ New Pull Request πŸ’ͺ - SLACK_MESSAGE: ${{steps.prmarkdown.outputs.text}} - MSG_MINIMAL: true + discussion: + if: github.event_name == 'discussion' && github.actor != 'asyncapi-bot' && github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' + name: Notify slack on every new pull request + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Convert markdown to slack markdown for pull request + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: discussionmarkdown + with: + markdown: "[${{github.event.discussion.title}}](${{github.event.discussion.html_url}}) \n ${{github.event.discussion.body}}" + - name: Send info about pull request + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_GITHUB_NEWISSUEPR}} + SLACK_TITLE: πŸ’¬ New Discussion in ${{github.repository}} πŸ’¬ + SLACK_MESSAGE: ${{steps.discussionmarkdown.outputs.text}} + MSG_MINIMAL: true diff --git a/.github/workflows/lighthouse-ci.yml b/.github/workflows/lighthouse-ci.yml new file mode 100644 index 000000000000..137d2fb77e8e --- /dev/null +++ b/.github/workflows/lighthouse-ci.yml @@ -0,0 +1,95 @@ +name: Lighthouse CI + +on: + pull_request_target: + branches: + - master + types: [opened, reopened, synchronize, ready_for_review] + +jobs: + lighthouse-ci: + name: Lighthouse CI + runs-on: ubuntu-latest + + steps: + - if: > + !github.event.pull_request.draft && !( + (github.actor == 'asyncapi-bot' && ( + startsWith(github.event.pull_request.title, 'ci: update global workflows') || + startsWith(github.event.pull_request.title, 'chore: update code of conduct') || + startsWith(github.event.pull_request.title, 'ci: update global contribution guide') || + startsWith(github.event.pull_request.title, 'ci: update workflows for go projects') || + startsWith(github.event.pull_request.title, 'ci: update workflows for nodejs projects') || + startsWith(github.event.pull_request.title, 'ci: update release-related workflows for nodejs projects') || + startsWith(github.event.pull_request.title, 'ci: update semantic release config file') || + startsWith(github.event.pull_request.title, 'ci: update generic workflows') || + startsWith(github.event.pull_request.title, 'ci: update workflows for docker-based projects') || + startsWith(github.event.pull_request.title, 'chore(release):') + )) || + (github.actor == 'allcontributors[bot]' && + startsWith(github.event.pull_request.title, 'docs: add') + ) + ) + id: should_run + name: Should Run + run: echo "::set-output name=shouldrun::true" + + - if: steps.should_run.outputs.shouldrun == 'true' + uses: actions/checkout@v3 + + - if: steps.should_run.outputs.shouldrun == 'true' + name: Await Netlify Preview + uses: jakepartusch/wait-for-netlify-action@v1 + id: netlify + with: + site_name: asyncapi-website + max_timeout: 600 + + - if: steps.should_run.outputs.shouldrun == 'true' + name: Lighthouse Audit + id: lighthouse_audit + uses: treosh/lighthouse-ci-action@9.3.0 + with: + urls: | + https://deploy-preview-$PR_NUMBER--asyncapi-website.netlify.app/ + configPath: ./.github/workflows/lighthouserc.json + uploadArtifacts: true + temporaryPublicStorage: true + env: + PR_NUMBER: ${{ github.event.pull_request.number}} + + - if: steps.should_run.outputs.shouldrun == 'true' + name: Lighthouse Score Report + id: lighthouse_score_report + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const result = ${{ steps.lighthouse_audit.outputs.manifest }}[0].summary + const links = ${{ steps.lighthouse_audit.outputs.links }} + const formatResult = (res) => Math.round((res * 100)) + Object.keys(result).forEach(key => result[key] = formatResult(result[key])) + const score = res => res >= 90 ? '🟒' : res >= 50 ? '🟠' : 'πŸ”΄' + const comment = [ + `⚑️ [Lighthouse report](${Object.values(links)[0]}) for the changes in this PR:`, + '| Category | Score |', + '| --- | --- |', + `| ${score(result.performance)} Performance | ${result.performance} |`, + `| ${score(result.accessibility)} Accessibility | ${result.accessibility} |`, + `| ${score(result['best-practices'])} Best practices | ${result['best-practices']} |`, + `| ${score(result.seo)} SEO | ${result.seo} |`, + `| ${score(result.pwa)} PWA | ${result.pwa} |`, + ' ', + `*Lighthouse ran on [${Object.keys(links)[0]}](${Object.keys(links)[0]})*` + ].join('\n') + core.setOutput("comment", comment); + + - if: steps.should_run.outputs.shouldrun == 'true' + name: LightHouse Statistic Comment + id: lighthouse_statistic_comment + uses: marocchino/sticky-pull-request-comment@v2.2.0 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ github.event.pull_request.number }} + header: lighthouse + message: ${{ steps.lighthouse_score_report.outputs.comment }} diff --git a/.github/workflows/lighthouserc.json b/.github/workflows/lighthouserc.json new file mode 100644 index 000000000000..b1a3b6642d9a --- /dev/null +++ b/.github/workflows/lighthouserc.json @@ -0,0 +1,23 @@ +{ + "ci": { + "assert": { + "assertions": { + "categories:accessibility": ["error", {"minScore": 0.98}], + "categories:best-practices": ["error", {"minScore": 1.00}], + "categories:seo": ["error", {"minScore": 1.00}] + } + }, + "collect": { + "settings": { + "skipAudits": [ + "robots-txt", + "canonical", + "tap-targets", + "is-crawlable", + "works-offline", + "offline-start-url" + ] + } + } + } + } diff --git a/.github/workflows/lint-pr-title.yml b/.github/workflows/lint-pr-title.yml index fbee657e99ae..77aa1c6e4d61 100644 --- a/.github/workflows/lint-pr-title.yml +++ b/.github/workflows/lint-pr-title.yml @@ -1,22 +1,47 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo name: Lint PR title on: - pull_request_target: types: [opened, reopened, synchronize, edited, ready_for_review] jobs: - - lint: - runs-on: ubuntu-latest - steps: - - uses: amannn/action-semantic-pull-request@v3.2.5 + lint-pr-title: + name: Lint PR title + runs-on: ubuntu-latest + steps: + # Since this workflow is REQUIRED for a PR to be mergable, we have to have this 'if' statement in step level instead of job level. + - if: ${{ !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor) }} + uses: amannn/action-semantic-pull-request@c3cd5d1ea3580753008872425915e343e351ab54 #version 5.2.0 https://github.com/amannn/action-semantic-pull-request/releases/tag/v5.2.0 + id: lint_pr_title env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GH_TOKEN}} with: subjectPattern: ^(?![A-Z]).+$ subjectPatternError: | The subject "{subject}" found in the pull request title "{title}" should start with a lowercase character. + + # Comments the error message from the above lint_pr_title action + - if: ${{ always() && steps.lint_pr_title.outputs.error_message != null && !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor)}} + name: Comment on PR + uses: marocchino/sticky-pull-request-comment@3d60a5b2dae89d44e0c6ddc69dd7536aec2071cd #use 2.5.0 https://github.com/marocchino/sticky-pull-request-comment/releases/tag/v2.5.0 + with: + header: pr-title-lint-error + GITHUB_TOKEN: ${{ secrets.GH_TOKEN}} + message: | + + We require all PRs to follow [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/). + More details πŸ‘‡πŸΌ + ``` + ${{ steps.lint_pr_title.outputs.error_message}} + ``` + # deletes the error comment if the title is correct + - if: ${{ steps.lint_pr_title.outputs.error_message == null }} + name: delete the comment + uses: marocchino/sticky-pull-request-comment@3d60a5b2dae89d44e0c6ddc69dd7536aec2071cd #use 2.5.0 https://github.com/marocchino/sticky-pull-request-comment/releases/tag/v2.5.0 + with: + header: pr-title-lint-error + delete: true + GITHUB_TOKEN: ${{ secrets.GH_TOKEN}} diff --git a/.github/workflows/notify-tsc-members-mention.yml b/.github/workflows/notify-tsc-members-mention.yml new file mode 100644 index 000000000000..d72fd85bdbe3 --- /dev/null +++ b/.github/workflows/notify-tsc-members-mention.yml @@ -0,0 +1,297 @@ +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + +# This action notifies community on slack whenever there is a new issue, PR or discussion started in given repository +name: Notify slack and email subscribers whenever TSC members are mentioned in GitHub + +on: + issue_comment: + types: + - created + + discussion_comment: + types: + - created + + issues: + types: + - opened + + pull_request_target: + types: + - opened + + discussion: + types: + - created + +jobs: + issue: + if: github.event_name == 'issues' && contains(github.event.issue.body, '@asyncapi/tsc_members') + name: TSC notification on every new issue + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + ######### + # Handling Slack notifications + ######### + - name: Convert markdown to slack markdown + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: issuemarkdown + with: + markdown: "[${{github.event.issue.title}}](${{github.event.issue.html_url}}) \n ${{github.event.issue.body}}" + - name: Send info about issue + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_TSC_MEMBERS_NOTIFY}} + SLACK_TITLE: πŸ†˜ New issue that requires TSC Members attention πŸ†˜ + SLACK_MESSAGE: ${{steps.issuemarkdown.outputs.text}} + MSG_MINIMAL: true + ######### + # Handling Mailchimp notifications + ######### + - name: Install deps + run: npm install + working-directory: ./.github/workflows/scripts/mailchimp + - name: Send email with MailChimp + uses: actions/github-script@v6 + env: + CALENDAR_ID: ${{ secrets.CALENDAR_ID }} + CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} + MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + with: + script: | + const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); + sendEmail('${{github.event.issue.html_url}}', '${{github.event.issue.title}}'); + + pull_request: + if: github.event_name == 'pull_request_target' && contains(github.event.pull_request.body, '@asyncapi/tsc_members') + name: TSC notification on every new pull request + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + ######### + # Handling Slack notifications + ######### + - name: Convert markdown to slack markdown + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: prmarkdown + with: + markdown: "[${{github.event.pull_request.title}}](${{github.event.pull_request.html_url}}) \n ${{github.event.pull_request.body}}" + - name: Send info about pull request + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_TSC_MEMBERS_NOTIFY}} + SLACK_TITLE: πŸ†˜ New PR that requires TSC Members attention πŸ†˜ + SLACK_MESSAGE: ${{steps.prmarkdown.outputs.text}} + MSG_MINIMAL: true + ######### + # Handling Mailchimp notifications + ######### + - name: Install deps + run: npm install + working-directory: ./.github/workflows/scripts/mailchimp + - name: Send email with MailChimp + uses: actions/github-script@v6 + env: + CALENDAR_ID: ${{ secrets.CALENDAR_ID }} + CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} + MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + with: + script: | + const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); + sendEmail('${{github.event.pull_request.html_url}}', '${{github.event.pull_request.title}}'); + + discussion: + if: github.event_name == 'discussion' && contains(github.event.discussion.body, '@asyncapi/tsc_members') + name: TSC notification on every new discussion + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + ######### + # Handling Slack notifications + ######### + - name: Convert markdown to slack markdown + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: discussionmarkdown + with: + markdown: "[${{github.event.discussion.title}}](${{github.event.discussion.html_url}}) \n ${{github.event.discussion.body}}" + - name: Send info about pull request + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_TSC_MEMBERS_NOTIFY}} + SLACK_TITLE: πŸ†˜ New discussion that requires TSC Members attention πŸ†˜ + SLACK_MESSAGE: ${{steps.discussionmarkdown.outputs.text}} + MSG_MINIMAL: true + ######### + # Handling Mailchimp notifications + ######### + - name: Install deps + run: npm install + working-directory: ./.github/workflows/scripts/mailchimp + - name: Send email with MailChimp + uses: actions/github-script@v6 + env: + CALENDAR_ID: ${{ secrets.CALENDAR_ID }} + CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} + MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + with: + script: | + const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); + sendEmail('${{github.event.discussion.html_url}}', '${{github.event.discussion.title}}'); + + issue_comment: + if: ${{ github.event_name == 'issue_comment' && !github.event.issue.pull_request && contains(github.event.comment.body, '@asyncapi/tsc_members') }} + name: TSC notification on every new comment in issue + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + ######### + # Handling Slack notifications + ######### + - name: Convert markdown to slack markdown + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: issuemarkdown + with: + markdown: "[${{github.event.issue.title}}](${{github.event.comment.html_url}}) \n ${{github.event.comment.body}}" + - name: Send info about issue comment + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_TSC_MEMBERS_NOTIFY}} + SLACK_TITLE: πŸ†˜ New comment under existing issue that requires TSC Members attention πŸ†˜ + SLACK_MESSAGE: ${{steps.issuemarkdown.outputs.text}} + MSG_MINIMAL: true + ######### + # Handling Mailchimp notifications + ######### + - name: Install deps + run: npm install + working-directory: ./.github/workflows/scripts/mailchimp + - name: Send email with MailChimp + uses: actions/github-script@v6 + env: + CALENDAR_ID: ${{ secrets.CALENDAR_ID }} + CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} + MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + with: + script: | + const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); + sendEmail('${{github.event.comment.html_url}}', '${{github.event.issue.title}}'); + + pr_comment: + if: github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '@asyncapi/tsc_members') + name: TSC notification on every new comment in pr + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + ######### + # Handling Slack notifications + ######### + - name: Convert markdown to slack markdown + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: prmarkdown + with: + markdown: "[${{github.event.issue.title}}](${{github.event.comment.html_url}}) \n ${{github.event.comment.body}}" + - name: Send info about PR comment + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_TSC_MEMBERS_NOTIFY}} + SLACK_TITLE: πŸ†˜ New comment under existing PR that requires TSC Members attention πŸ†˜ + SLACK_MESSAGE: ${{steps.prmarkdown.outputs.text}} + MSG_MINIMAL: true + ######### + # Handling Mailchimp notifications + ######### + - name: Install deps + run: npm install + working-directory: ./.github/workflows/scripts/mailchimp + - name: Send email with MailChimp + uses: actions/github-script@v6 + env: + CALENDAR_ID: ${{ secrets.CALENDAR_ID }} + CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} + MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + with: + script: | + const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); + sendEmail('${{github.event.comment.html_url}}', '${{github.event.issue.title}}'); + + discussion_comment: + if: github.event_name == 'discussion_comment' && contains(github.event.comment.body, '@asyncapi/tsc_members') + name: TSC notification on every new comment in discussion + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + ######### + # Handling Slack notifications + ######### + - name: Convert markdown to slack markdown + uses: asyncapi/.github/.github/actions/slackify-markdown@master + id: discussionmarkdown + with: + markdown: "[${{github.event.discussion.title}}](${{github.event.comment.html_url}}) \n ${{github.event.comment.body}}" + - name: Send info about discussion comment + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{secrets.SLACK_TSC_MEMBERS_NOTIFY}} + SLACK_TITLE: πŸ†˜ New comment under existing discussion that requires TSC Members attention πŸ†˜ + SLACK_MESSAGE: ${{steps.discussionmarkdown.outputs.text}} + MSG_MINIMAL: true + ######### + # Handling Mailchimp notifications + ######### + - name: Install deps + run: npm install + working-directory: ./.github/workflows/scripts/mailchimp + - name: Send email with MailChimp + uses: actions/github-script@v6 + env: + CALENDAR_ID: ${{ secrets.CALENDAR_ID }} + CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} + MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + with: + script: | + const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); + sendEmail('${{github.event.comment.html_url}}', '${{github.event.discussion.title}}'); diff --git a/.github/workflows/regenerate-meetings-and-videos.yml b/.github/workflows/regenerate-meetings-and-videos.yml new file mode 100644 index 000000000000..0430c2c40893 --- /dev/null +++ b/.github/workflows/regenerate-meetings-and-videos.yml @@ -0,0 +1,43 @@ +name: List everyday latest list of AsyncAPI Meetings, Newsroom Videos and Dashboard data. + +on: + workflow_dispatch: + schedule: + #every day at midnight + - cron: "10 0 * * *" + +jobs: + meetings: + if: github.repository == 'asyncapi/website' + env: + CALENDAR_ID: ${{ secrets.CALENDAR_ID }} + CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} + YOUTUBE_TOKEN: ${{ secrets.YOUTUBE_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + name: Regenerate meetings.json and dashboard.json + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Install dependencies + run: npm install + - name: Regenerate + run: npm run generate:meetings && npm run generate:videos && npm run generate:dashboard + - name: Create Pull Request with new meetings.json, newsroom-videos.json and dashboard.json version + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GH_TOKEN }} + commit-message: 'chore: update meetings.json, newsrooom_videos.json and dashboard.json' + committer: asyncapi-bot + author: asyncapi-bot + title: 'chore: update meetings.json and newsrooom_videos.json' + branch: update-meetings/${{ github.job }} + - if: failure() # Only, on failure, send a message on the 94_bot-failing-ci slack channel + name: Report workflow run status to Slack + uses: 8398a7/action-slack@v3 + with: + status: ${{ job.status }} + fields: repo,action,workflow + text: 'AsyncAPI Meetings and Videos workflow failed' + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CI_FAIL_NOTIFY }} \ No newline at end of file diff --git a/.github/workflows/regenerate-tools.yml b/.github/workflows/regenerate-tools.yml new file mode 100644 index 000000000000..1db90e0e34f2 --- /dev/null +++ b/.github/workflows/regenerate-tools.yml @@ -0,0 +1,44 @@ +name: List of all the tools used in AsyncAPI + +on: + workflow_dispatch: + schedule: + #every day at midnight + - cron: "15 0 * * 1" + +jobs: + regenerateTools: + if: github.repository == 'asyncapi/website' + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + name: Regenerate tools.json + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: 16.x + - name: Install dependencies + run: npm install + - name: Regenerate + run: npm run generate:tools + - name: Create Pull Request with new tools.json version + uses: peter-evans/create-pull-request@v4 + with: + token: ${{ secrets.GH_TOKEN }} + commit-message: 'chore: update tools.json' + committer: asyncapi-bot + author: asyncapi-bot + title: 'chore: update tools.json' + branch: update-tools/${{ github.job }} + - if: failure() # Only, on failure, send a message on the 94_bot-failing-ci slack channel + name: Report workflow run status to Slack + uses: 8398a7/action-slack@v3 + with: + status: ${{ job.status }} + fields: repo,action,workflow + text: 'AsyncAPI Tools workflow failed' + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CI_FAIL_NOTIFY }} \ No newline at end of file diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 653ca286610c..9587caceeb41 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -1,5 +1,6 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + name: 'Announce releases in different channels' on: @@ -9,15 +10,17 @@ on: jobs: - slack: + slack-announce: name: Slack - notify on every release runs-on: ubuntu-latest steps: + - name: Checkout repository + uses: actions/checkout@v3 - name: Convert markdown to slack markdown for issue - uses: LoveToKnow/slackify-markdown-action@v1.0.0 + uses: asyncapi/.github/.github/actions/slackify-markdown@master id: markdown with: - text: "[${{github.event.release.tag_name}}](${{github.event.release.html_url}}) \n ${{ github.event.release.body }}" + markdown: "[${{github.event.release.tag_name}}](${{github.event.release.html_url}}) \n ${{ github.event.release.body }}" - name: Send info about release to Slack uses: rtCamp/action-slack-notify@v2 env: @@ -26,14 +29,14 @@ jobs: SLACK_MESSAGE: ${{steps.markdown.outputs.text}} MSG_MINIMAL: true - twitter: + twitter-announce: name: Twitter - notify on minor and major releases runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Get version of last and previous release - uses: actions/github-script@v3 + uses: actions/github-script@v6 id: versions with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -59,15 +62,15 @@ jobs: - name: Identify release type id: releasetype # if previousver is not provided then this steps just logs information about missing version, no errors - run: echo "::set-output name=type::$(npx -q -p semver-diff-cli semver-diff ${{steps.versions.outputs.previousver}} ${{steps.versions.outputs.lastver}})" + run: echo "type=$(npx -q -p semver-diff-cli semver-diff ${{steps.versions.outputs.previousver}} ${{steps.versions.outputs.lastver}})" >> $GITHUB_OUTPUT - name: Get name of the person that is behind the newly released version id: author - run: echo "::set-output name=name::$(git log -1 --pretty=format:'%an')" + run: echo "name=$(git log -1 --pretty=format:'%an')" >> $GITHUB_OUTPUT - name: Publish information about the release to Twitter # tweet only if detected version change is not a patch # tweet goes out even if the type is not major or minor but "You need provide version number to compare." # it is ok, it just means we did not identify previous version as we are tweeting out information about the release for the first time if: steps.releasetype.outputs.type != 'null' && steps.releasetype.outputs.type != 'patch' # null means that versions are the same - uses: m1ner79/Github-Twittction@v1.0.1 + uses: m1ner79/Github-Twittction@d1e508b6c2170145127138f93c49b7c46c6ff3a7 # using 2.0.0 https://github.com/m1ner79/Github-Twittction/releases/tag/v2.0.0 with: twitter_status: "Release ${{github.event.release.tag_name}} for ${{github.repository}} is out in the wild 😱πŸ’ͺπŸΎπŸŽ‚\n\nThank you for the contribution ${{ steps.author.outputs.name }} ${{github.event.release.html_url}}" twitter_consumer_key: ${{ secrets.TWITTER_CONSUMER_KEY }} diff --git a/.github/workflows/scripts/README.md b/.github/workflows/scripts/README.md new file mode 100644 index 000000000000..ba97dca075d0 --- /dev/null +++ b/.github/workflows/scripts/README.md @@ -0,0 +1 @@ +The entire `scripts` directory is centrally managed in [.github](https://github.com/asyncapi/.github/) repository. Any changes in this folder should be done in central repository. \ No newline at end of file diff --git a/.github/workflows/scripts/mailchimp/htmlContent.js b/.github/workflows/scripts/mailchimp/htmlContent.js new file mode 100644 index 000000000000..d132c72f1aa0 --- /dev/null +++ b/.github/workflows/scripts/mailchimp/htmlContent.js @@ -0,0 +1,495 @@ +/** + * This code is centrally managed in https://github.com/asyncapi/.github/ + * Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + */ +module.exports = (link, title) => { + + return ` + + + + + + + + *|MC:SUBJECT|* + + + + + + +
+ + + + +
+ + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + +
+ + Hey *|FNAME|*,
+
+There is a new topic at AsyncAPI Initiative that requires Technical Steering Committee attention. +
+Please have a look if it is just something you need to be aware of, or maybe your vote is needed. +
+Topic: ${ title }. +
+ + + +
+ + + + + + + +
+ + + + + + + + +
+ + Cheers,
+AsyncAPI Initiative +
+ + + +
+ + + + + +
+ + + + + + + + +
+ + Want to change how you receive these emails?
+You can update your preferences or unsubscribe from this list.
+  +
+ + + +
+ + +
+
+ + +` +} \ No newline at end of file diff --git a/.github/workflows/scripts/mailchimp/index.js b/.github/workflows/scripts/mailchimp/index.js new file mode 100644 index 000000000000..4a200c6c48b6 --- /dev/null +++ b/.github/workflows/scripts/mailchimp/index.js @@ -0,0 +1,79 @@ +/** + * This code is centrally managed in https://github.com/asyncapi/.github/ + * Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo + */ +const mailchimp = require('@mailchimp/mailchimp_marketing'); +const core = require('@actions/core'); +const htmlContent = require('./htmlContent.js'); + +/** + * Sending API request to mailchimp to schedule email to subscribers + * Input is the URL to issue/discussion or other resource + */ +module.exports = async (link, title) => { + + let newCampaign; + + mailchimp.setConfig({ + apiKey: process.env.MAILCHIMP_API_KEY, + server: 'us12' + }); + + /* + * First we create campaign + */ + try { + newCampaign = await mailchimp.campaigns.create({ + type: 'regular', + recipients: { + list_id: '6e3e437abe', + segment_opts: { + match: 'any', + conditions: [{ + condition_type: 'Interests', + field: 'interests-2801e38b9f', + op: 'interestcontains', + value: ['f7204f9b90'] + }] + } + }, + settings: { + subject_line: `TSC attention required: ${ title }`, + preview_text: 'Check out the latest topic that TSC members have to be aware of', + title: `New topic info - ${ new Date(Date.now()).toUTCString()}`, + from_name: 'AsyncAPI Initiative', + reply_to: 'info@asyncapi.io', + } + }); + } catch (error) { + return core.setFailed(`Failed creating campaign: ${ JSON.stringify(error) }`); + } + + /* + * Content of the email is added separately after campaign creation + */ + try { + await mailchimp.campaigns.setContent(newCampaign.id, { html: htmlContent(link, title) }); + } catch (error) { + return core.setFailed(`Failed adding content to campaign: ${ JSON.stringify(error) }`); + } + + /* + * We schedule an email to send it immediately + */ + try { + //schedule for next hour + //so if this code was created by new issue creation at 9:46, the email is scheduled for 10:00 + //is it like this as schedule has limitiations and you cannot schedule email for 9:48 + const scheduleDate = new Date(Date.parse(new Date(Date.now()).toISOString()) + 1 * 1 * 60 * 60 * 1000); + scheduleDate.setUTCMinutes(00); + + await mailchimp.campaigns.schedule(newCampaign.id, { + schedule_time: scheduleDate.toISOString(), + }); + } catch (error) { + return core.setFailed(`Failed scheduling email: ${ JSON.stringify(error) }`); + } + + core.info(`New email campaign created`); +} \ No newline at end of file diff --git a/.github/workflows/scripts/mailchimp/package-lock.json b/.github/workflows/scripts/mailchimp/package-lock.json new file mode 100644 index 000000000000..7ee7d84f86f4 --- /dev/null +++ b/.github/workflows/scripts/mailchimp/package-lock.json @@ -0,0 +1,597 @@ +{ + "name": "schedule-email", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "schedule-email", + "license": "Apache 2.0", + "dependencies": { + "@actions/core": "1.6.0", + "@mailchimp/mailchimp_marketing": "3.0.74" + } + }, + "node_modules/@actions/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", + "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==", + "dependencies": { + "@actions/http-client": "^1.0.11" + } + }, + "node_modules/@actions/http-client": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", + "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", + "dependencies": { + "tunnel": "0.0.6" + } + }, + "node_modules/@mailchimp/mailchimp_marketing": { + "version": "3.0.74", + "resolved": "https://registry.npmjs.org/@mailchimp/mailchimp_marketing/-/mailchimp_marketing-3.0.74.tgz", + "integrity": "sha512-039iu4GRr7wpXqweBLuS05wvOBtPxSa31cjxgftBYSt7031f0sHEi8Up2DicfbSuQK0AynPDeVyuxrb31Lx+yQ==", + "dependencies": { + "dotenv": "^8.2.0", + "superagent": "3.8.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/superagent": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.1.tgz", + "integrity": "sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==", + "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + }, + "dependencies": { + "@actions/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", + "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==", + "requires": { + "@actions/http-client": "^1.0.11" + } + }, + "@actions/http-client": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", + "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", + "requires": { + "tunnel": "0.0.6" + } + }, + "@mailchimp/mailchimp_marketing": { + "version": "3.0.74", + "resolved": "https://registry.npmjs.org/@mailchimp/mailchimp_marketing/-/mailchimp_marketing-3.0.74.tgz", + "integrity": "sha512-039iu4GRr7wpXqweBLuS05wvOBtPxSa31cjxgftBYSt7031f0sHEi8Up2DicfbSuQK0AynPDeVyuxrb31Lx+yQ==", + "requires": { + "dotenv": "^8.2.0", + "superagent": "3.8.1" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "superagent": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.1.tgz", + "integrity": "sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==", + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } +} \ No newline at end of file diff --git a/.github/workflows/scripts/mailchimp/package.json b/.github/workflows/scripts/mailchimp/package.json new file mode 100644 index 000000000000..cc50e43e0298 --- /dev/null +++ b/.github/workflows/scripts/mailchimp/package.json @@ -0,0 +1,9 @@ +{ + "name": "schedule-email", + "description": "This code is responsible for scheduling an email campaign. This file is centrally managed in https://github.com/asyncapi/.github/", + "license": "Apache 2.0", + "dependencies": { + "@actions/core": "1.6.0", + "@mailchimp/mailchimp_marketing": "3.0.74" + } +} \ No newline at end of file diff --git a/.github/workflows/sentiment-analysis.yml b/.github/workflows/sentiment-analysis.yml deleted file mode 100644 index 431d1937e691..000000000000 --- a/.github/workflows/sentiment-analysis.yml +++ /dev/null @@ -1,44 +0,0 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo - -name: 'Sentiment Analysis' - -on: - issue_comment: - types: - - created - - edited - issues: - types: - - opened - - edited - pull_request: - types: - - opened - - edited - pull_request_review: - types: - - submitted - - edited - pull_request_review_comment: - types: - - created - - edited -jobs: - test: - name: Checking sentiments - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Check sentiment - uses: derberg/code-of-conduct-sentiment-analysis-github-action@v1 - id: sentiments - with: - gcp_key: ${{ secrets.GCP_KEY_SENTIMENT }} - - uses: someimportantcompany/github-actions-slack-message@v1 - # this step runs only if sentiment is a negative number - if: steps.sentiments.outputs.sentiment < -0.6 - with: - webhook-url: ${{ secrets.SLACK_SENTIMENTS }} - text: Here ${{steps.sentiments.outputs.source}} you can find a potential negative text that requires your attention as the sentiment analysis score is ${{steps.sentiments.outputs.sentiment}} - color: orange \ No newline at end of file diff --git a/.github/workflows/stale-issues-prs.yml b/.github/workflows/stale-issues-prs.yml index f1c6a8367e84..ed1fcf19ab11 100644 --- a/.github/workflows/stale-issues-prs.yml +++ b/.github/workflows/stale-issues-prs.yml @@ -1,5 +1,5 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo name: Manage stale issues and PRs @@ -9,22 +9,37 @@ on: jobs: stale: + if: startsWith(github.repository, 'asyncapi/') + name: Mark issue or PR as stale runs-on: ubuntu-latest steps: - - uses: actions/stale@v1.1.0 + - uses: actions/stale@99b6c709598e2b0d0841cd037aaf1ba07a4410bd #v5.2.0 but pointing to commit for security reasons with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: | This issue has been automatically marked as stale because it has not had recent activity :sleeping: - It will be closed in 60 days if no further activity occurs. To unstale this issue, add a comment with detailed explanation. - Thank you for your contributions :heart: + + It will be closed in 120 days if no further activity occurs. To unstale this issue, add a comment with a detailed explanation. + + There can be many reasons why some specific issue has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under [open governance model](https://github.com/asyncapi/community/blob/master/CHARTER.md). + + Let us figure out together how to push this issue forward. Connect with us through [one of many communication channels](https://github.com/asyncapi/community/issues/1) we established here. + + Thank you for your patience :heart: stale-pr-message: | This pull request has been automatically marked as stale because it has not had recent activity :sleeping: - It will be closed in 60 days if no further activity occurs. To unstale this pull request, add a comment with detailed explanation. - Thank you for your contributions :heart: - days-before-stale: 60 - days-before-close: 60 + + It will be closed in 120 days if no further activity occurs. To unstale this pull request, add a comment with detailed explanation. + + There can be many reasons why some specific pull request has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under [open governance model](https://github.com/asyncapi/community/blob/master/CHARTER.md). + + Let us figure out together how to push this pull request forward. Connect with us through [one of many communication channels](https://github.com/asyncapi/community/issues/1) we established here. + + Thank you for your patience :heart: + days-before-stale: 120 + days-before-close: 120 stale-issue-label: stale stale-pr-label: stale - exempt-issue-label: keep-open - exempt-pr-label: keep-open \ No newline at end of file + exempt-issue-labels: keep-open + exempt-pr-labels: keep-open + close-issue-reason: not_planned diff --git a/.github/workflows/welcome-first-time-contrib.yml b/.github/workflows/welcome-first-time-contrib.yml index e687e75a3736..cbc23ce7c2fb 100644 --- a/.github/workflows/welcome-first-time-contrib.yml +++ b/.github/workflows/welcome-first-time-contrib.yml @@ -1,5 +1,5 @@ -#This action is centrally managed in https://github.com/asyncapi/.github/ -#Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo +# This action is centrally managed in https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in above mentioned repo name: Welcome first time contributors @@ -13,18 +13,73 @@ on: jobs: welcome: + name: Post welcome message + if: ${{ !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor) }} runs-on: ubuntu-latest steps: - - uses: actions/first-interaction@v1 + - uses: actions/github-script@v6 with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - issue-message: | - Welcome to AsyncAPI. Thanks a lot for reporting your first issue. Please check out our [contributors guide](https://github.com/asyncapi/.github/blob/master/CONTRIBUTING.md) and the instructions about a [basic recommended setup](https://github.com/asyncapi/.github/blob/master/git-workflow.md) useful for opening a pull request. - - Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out [this issue](https://github.com/asyncapi/asyncapi/issues/115). - - - pr-message: | - Welcome to AsyncAPI. Thanks a lot for creating your first pull request. Please check out our [contributors guide](https://github.com/asyncapi/.github/blob/master/CONTRIBUTING.md) and the instructions about a [basic recommended setup](https://github.com/asyncapi/.github/blob/master/git-workflow.md) useful for opening a pull request. - - Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out [this issue](https://github.com/asyncapi/asyncapi/issues/115). + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const issueMessage = `Welcome to AsyncAPI. Thanks a lot for reporting your first issue. Please check out our [contributors guide](https://github.com/asyncapi/community/blob/master/CONTRIBUTING.md) and the instructions about a [basic recommended setup](https://github.com/asyncapi/community/blob/master/git-workflow.md) useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out [this issue](https://github.com/asyncapi/asyncapi/issues/115).`; + const prMessage = `Welcome to AsyncAPI. Thanks a lot for creating your first pull request. Please check out our [contributors guide](https://github.com/asyncapi/community/blob/master/CONTRIBUTING.md) useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out [this issue](https://github.com/asyncapi/asyncapi/issues/115).`; + if (!issueMessage && !prMessage) { + throw new Error('Action must have at least one of issue-message or pr-message set'); + } + const isIssue = !!context.payload.issue; + let isFirstContribution; + if (isIssue) { + const query = `query($owner:String!, $name:String!, $contributer:String!) { + repository(owner:$owner, name:$name){ + issues(first: 1, filterBy: {createdBy:$contributer}){ + totalCount + } + } + }`; + const variables = { + owner: context.repo.owner, + name: context.repo.repo, + contributer: context.payload.sender.login + }; + const { repository: { issues: { totalCount } } } = await github.graphql(query, variables); + isFirstContribution = totalCount === 1; + } else { + const query = `query($qstr: String!) { + search(query: $qstr, type: ISSUE, first: 1) { + issueCount + } + }`; + const variables = { + "qstr": `repo:${context.repo.owner}/${context.repo.repo} type:pr author:${context.payload.sender.login}`, + }; + const { search: { issueCount } } = await github.graphql(query, variables); + isFirstContribution = issueCount === 1; + } + + if (!isFirstContribution) { + console.log(`Not the users first contribution.`); + return; + } + const message = isIssue ? issueMessage : prMessage; + // Add a comment to the appropriate place + if (isIssue) { + const issueNumber = context.payload.issue.number; + console.log(`Adding message: ${message} to issue #${issueNumber}`); + await github.rest.issues.createComment({ + owner: context.payload.repository.owner.login, + repo: context.payload.repository.name, + issue_number: issueNumber, + body: message + }); + } + else { + const pullNumber = context.payload.pull_request.number; + console.log(`Adding message: ${message} to pull request #${pullNumber}`); + await github.rest.pulls.createReview({ + owner: context.payload.repository.owner.login, + repo: context.payload.repository.name, + pull_number: pullNumber, + body: message, + event: 'COMMENT' + }); + } diff --git a/.gitignore b/.gitignore index 237b63453f72..ed771f133ca6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,13 @@ .idea node_modules .next +.swc +out config/posts.json +config/case-studies.json +public/rss.xml .env.local -roadmap.json \ No newline at end of file +yarn.lock +meetings.json +.netlify +.env diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 000000000000..939c95fffdf1 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,9 @@ +# List the start up tasks. Learn more https://www.gitpod.io/docs/config-start-tasks/ +tasks: + - init: npm install # runs during prebuild + command: npm run dev + +# List the ports to expose. Learn more https://www.gitpod.io/docs/config-ports/ +ports: + - port: 3000 + onOpen: open-preview diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000000..04e81e8c8446 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,13 @@ +# This file provides an overview of code owners in this repository. + +# Each line is a file pattern followed by one or more owners. +# The last matching pattern has the most precedence. +# For more details, read the following article on GitHub: https://help.github.com/articles/about-codeowners/. + +# The default owners are automatically added as reviewers when you open a pull request unless different owners are specified in the file. +* @derberg @mcturco @akshatnema @magicmatatjahu @asyncapi-bot-eve + +# All .md files +*.md @alequetzalli @asyncapi-bot-eve + +README.md @alequetzalli @derberg @mcturco @akshatnema @magicmatatjahu @asyncapi-bot-eve diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000000..638f7334038c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at fmvilas@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000000..1334921c2813 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing to AsyncAPI +We love your input! We want to make contributing to this project as easy and transparent as possible. + +## Contribution recogniton + +We use [All Contributors](https://allcontributors.org/docs/en/specification) specification to handle recognitions. For more details read [this](https://github.com/asyncapi/community/blob/master/recognize-contributors.md) document. + +## Summary of the contribution flow + +The following is a summary of the ideal contribution flow. Please, note that Pull Requests can also be rejected by the maintainers when appropriate. + +``` + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ Open an issue β”‚ + β”‚ (a bug report or a β”‚ + β”‚ feature request) β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ⇩ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ Open a Pull Request β”‚ + β”‚ (only after issue β”‚ + β”‚ is approved) β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ⇩ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ Your changes will β”‚ + β”‚ be merged and β”‚ + β”‚ published on the next β”‚ + β”‚ release β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Code of Conduct +AsyncAPI has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](./CODE_OF_CONDUCT.md) so that you can understand what sort of behaviour is expected. + +## Our Development Process +We use Github to host code, to track issues and feature requests, as well as accept pull requests. + +## Issues +[Open an issue](https://github.com/asyncapi/asyncapi/issues/new) **only** if you want to report a bug or a feature. Don't open issues for questions or support, instead join our [Slack workspace](https://www.asyncapi.com/slack-invite) and ask there. Don't forget to follow our [Slack Etiquette](https://github.com/asyncapi/community/blob/master/slack-etiquette.md) while interacting with community members! It's more likely you'll get help, and much faster! + +## Bug Reports and Feature Requests + +Please use our issues templates that provide you with hints on what information we need from you to help you out. + +## Pull Requests + +**Please, make sure you open an issue before starting with a Pull Request, unless it's a typo or a really obvious error.** Pull requests are the best way to propose changes to the specification. Get familiar with our document that explains [Git workflow](https://github.com/asyncapi/community/blob/master/git-workflow.md) used in our repositories. + +## Conventional commits + +Our repositories follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification. Releasing to GitHub and NPM is done with the support of [semantic-release](https://semantic-release.gitbook.io/semantic-release/). + +Pull requests should have a title that follows the specification, otherwise, merging is blocked. If you are not familiar with the specification simply ask maintainers to modify. You can also use this cheatsheet if you want: + +- `fix: ` prefix in the title indicates that PR is a bug fix and PATCH release must be triggered. +- `feat: ` prefix in the title indicates that PR is a feature and MINOR release must be triggered. +- `docs: ` prefix in the title indicates that PR is only related to the documentation and there is no need to trigger release. +- `chore: ` prefix in the title indicates that PR is only related to cleanup in the project and there is no need to trigger release. +- `test: ` prefix in the title indicates that PR is only related to tests and there is no need to trigger release. +- `refactor: ` prefix in the title indicates that PR is only related to refactoring and there is no need to trigger release. + +What about MAJOR release? just add `!` to the prefix, like `fix!: ` or `refactor!: ` + +Prefix that follows specification is not enough though. Remember that the title must be clear and descriptive with usage of [imperative mood](https://chris.beams.io/posts/git-commit/#imperative). + +Happy contributing :heart: + +## License +When you submit changes, your submissions are understood to be under the same [Apache 2.0 License](https://github.com/asyncapi/asyncapi/blob/master/LICENSE) that covers the project. Feel free to [contact the maintainers](https://www.asyncapi.com/slack-invite) if that's a concern. + +## References +This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/master/CONTRIBUTING.md). \ No newline at end of file diff --git a/LICENSE b/LICENSE index f6dee7863215..6e0976e1f712 100644 --- a/LICENSE +++ b/LICENSE @@ -175,7 +175,7 @@ of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS -Copyright 2017 Fran MΓ©ndez +Copyright The Linux Foundation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -187,4 +187,4 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file +limitations under the License. diff --git a/README.md b/README.md index 1fcfdaded340..0216380d677b 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ -
- AsyncAPI logo -
- Website -
+[![AsyncAPI Banner and Logo](./public/img/logos/github-repobanner-website.png)](https://www.asyncapi.com) --- + +[![All Contributors](https://img.shields.io/badge/all_contributors-41-orange.svg?style=flat-square)](#contributors-) + + [![Netlify Status](https://api.netlify.com/api/v1/badges/b2137407-b765-46c4-95b5-a72d9b1592ab/deploy-status)](https://app.netlify.com/sites/asyncapi-website/deploys) ## Overview This repository contains the sources of AsyncAPI website: -- It's powered by [Next.js](https://nextjs.org/), +- It's powered by [Next.js](https://nextjs.org/), - It uses [Tailwind](https://tailwindcss.com/) CSS framework, - It's build and deployed with [Netlify](https://www.netlify.com/). @@ -20,28 +20,59 @@ This repository contains the sources of AsyncAPI website: Use the following tools to set up the project: -- [Node.js](https://nodejs.org/) v12.16+ -- [npm](https://www.npmjs.com/) v6.13.7+ +- [Node.js](https://nodejs.org/) v16.0.0+ +- [npm](https://www.npmjs.com/) v7.10.0+ + + +## Run locally + +1. Fork the repository by clicking on `Fork` option on top right of the main repository. + +2. Open Command Prompt on your local computer. + +3. Clone the forked repository by adding your own GitHub username in place of ``. + For multiple contributions it is recommended to have [proper configuration of forked repo](https://github.com/asyncapi/community/blob/master/git-workflow.md). + +```bash + git clone https://github.com//website/ +``` + +4. Navigate to the website directory. + +```bash + cd website +``` -## Usage +5. Install all website dependencies. -### Install dependencies +```bash + npm install +``` -To install all dependencies, run this command: +6. Run the website locally. ```bash -npm install + npm run dev ``` -### Develop +7. Access the live development server at [localhost:3000](http://localhost:3000). + -Launch the development server with the hot reloading functionality that allows any change in files to be immediately visible in the browser. Use this command: +## Compose new blog post + +To bootstrap a new post, run this command: ```bash -npm run dev + npm run write:blog ``` -You can access the live development server at [localhost:8080](http://localhost:8080). +Follow the interactive prompt to generate a post with pre-filled front matter. + +### Spin up Gitpod codespace + +In order to prepare and spin up a Gitpod dev environment for our project, we configured our workspace through a [.gitpod.yml](./.gitpod.yml) file. + +To spin up a Gitpod codespace, go to http://gitpod.io/#https://github.com/asyncapi/website. ### Build @@ -53,6 +84,35 @@ npm run build Generated files of the website go to the `.next` folder. +## Case studies + +### Overview + +A case study is a special document that any end-user company can provide. An end-user company is a company that uses AsyncAPI to solve technical challenges. A case study is not a document where a vendor company can describe how they build their commercial AsyncAPI-based product. On the other hand, it is completely fine if a case study of some end-user mentions some commercial tools that helped them to work with AsyncAPI or event-driven architecture. An example of such a case can be a case study from an end-user where at some point, Confluent Schema Registry is mentioned in an explanation about schemas and runtime message validation. + +### How to add a case study + +A case study is documented in the form of a YAML file. Anyone can open a pull request with a new case study. + +- YAML file must be located in `config/casestudies`. +- To make it easier for you to create such a YAML file you can use: + - [Template YAML with comments explaining every section](scripts/casestudies/casestudy_template.yml) + - [JSON Schema that describes all YAML fields](scripts/casestudies/schema.json) +- All additional files for the case study, like complete AsyncAPI document examples, should be located in the `public/resources/casestudies` directory. +- Company logo and other images that will be rendered in the website should be located in `public/img/casestudies`. + +Once you collect all information and create a case study, open a pull request. It must be authored or at least approved by a representative of the given company. Such a representative is probably already a contact person mentioned in the case study. + +A case study becomes publicly available right after merging and rebuilding the website. + +## JSON Schema definitions + +All AsyncAPI JSON Schema definition files are being served within the `/definitions/` path. The content is being served from GH, in particular from https://github.com/asyncapi/spec-json-schemas/tree/master/schemas. +This is possible thanks to the following: + +1. A [Netlify Rewrite rule](https://docs.netlify.com/routing/redirects/rewrites-proxies/) located in the [netlify.toml](netlify.toml) file, which acts as proxy for all requests to the `/definitions/` path, serving the content from GH without having an HTTP redirect. +2. A [Netlify Edge Function](https://docs.netlify.com/netlify-labs/experimental-features/edge-functions/) that modifies the `Content-Type` header of the rewrite response to become `application/schema+json`. This lets tooling, such as [Hyperjump](https://json-schema.hyperjump.io), to fetch the schemas directly from their URL. + ## Project structure This repository has the following structure: @@ -60,19 +120,94 @@ This repository has the following structure: ```text - β”œβ”€β”€ .github # Definitions of Github workflows, pull request and issue templates + β”œβ”€β”€ .github # Definitions of GitHub workflows, pull request and issue templates β”œβ”€β”€ components # Various generic components such as "Button", "Figure", etc. β”œβ”€β”€ config # Transformed static data to display on the pages such as blog posts etc. β”œβ”€β”€ context # Various React's contexts used in website β”œβ”€β”€ css # Various CSS files β”œβ”€β”€ lib # Various JS code for preparing static data to render in pages β”œβ”€β”€ pages # Website's pages source. It includes raw markdown files and React page templates. - β”‚ β”œβ”€β”€ about # Raw content for /about page + β”‚ β”œβ”€β”€ about # Raw blog for /about page β”‚ β”œβ”€β”€ blog # Blog posts - β”‚ └── docs # Content for /docs/* pages - β”œβ”€β”€ public # Data for site metadata and static content such as images + β”‚ β”œβ”€β”€ docs # Blog for /docs/* pages + β”‚ └── tools # Various pages to describe tools + β”œβ”€β”€ public # Data for site metadata and static blog such as images β”œβ”€β”€ scripts # Scripts used in the build and dev processes β”œβ”€β”€ next.config.js # Next.js configuration file + β”œβ”€β”€ netlify # Code that runs on Netlify + β”‚ β”œβ”€β”€ edge-functions # Netlify Edge-Functions code β”œβ”€β”€ postcss.config.js # PostCSS configuration file └── tailwind.config.js # TailwindCSS configuration file ``` + +## Contributors + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Fran MΓ©ndez
Fran MΓ©ndez

πŸ’» πŸ“– πŸ› 🎨 🚧 πŸš‡ πŸ€” πŸ‘€ πŸ“
Lukasz Gornicki
Lukasz Gornicki

πŸ’» πŸ“– πŸ› 🎨 🚧 πŸš‡ πŸ€” πŸ‘€ πŸ“
Maciej UrbaΕ„czyk
Maciej UrbaΕ„czyk

πŸ’» πŸ“– πŸ› 🎨 🚧 πŸš‡ πŸ€” πŸ‘€ πŸ“
Alejandra Quetzalli
Alejandra Quetzalli

πŸ“– πŸ‘€ πŸ“’
Aayush Kumar Sahu
Aayush Kumar Sahu

πŸ’» πŸ› 🎨
David Boyne
David Boyne

πŸ’» 🎨
Jesse Menning
Jesse Menning

πŸ“
Dimitrios Dedoussis
Dimitrios Dedoussis

πŸ“
Jonas Lagoni
Jonas Lagoni

πŸ“ πŸ’» πŸ‘€
Sergio Moya
Sergio Moya

πŸ’» πŸ“ πŸ‘€
Bodo Graumann
Bodo Graumann

πŸ“–
Damilola Randolph
Damilola Randolph

πŸ’»
Barbanio GonzΓ‘lez
Barbanio GonzΓ‘lez

πŸ“ πŸ€”
Hargun Kaur
Hargun Kaur

πŸ’»
Chris Eich
Chris Eich

πŸ‘€
Simone Fumagalli
Simone Fumagalli

πŸ“–
Missy Turco
Missy Turco

πŸ’» 🎨 πŸ€” πŸ‘€
Ritik Rawal
Ritik Rawal

πŸ’»
Akshat Nema
Akshat Nema

πŸ’»
David Pereira
David Pereira

πŸ’» πŸ“–
Debajyoti Halder
Debajyoti Halder

πŸ’»
Juan A.
Juan A.

πŸ’»
Muhammad Rafly Andrianza
Muhammad Rafly Andrianza

πŸ“–
Harish
Harish

πŸ’»
Paul Goldsmith
Paul Goldsmith

πŸ’» πŸ›
Tabah Baridule
Tabah Baridule

πŸ“–
Karuna Tata
Karuna Tata

️️️️♿️
Joseph Mawa
Joseph Mawa

πŸ‘€
Viacheslav Turovskyi
Viacheslav Turovskyi

πŸ“– πŸ’»
Helen Kosova
Helen Kosova

πŸ“–
V Thulisile Sibanda
V Thulisile Sibanda

πŸ“–
Manav Desai
Manav Desai

πŸ“–
Mohd Toukir Khan
Mohd Toukir Khan

πŸ“–
Anisat Akinbani
Anisat Akinbani

πŸ“–
sambhavgupta0705
sambhavgupta0705

πŸ’»
Ankit Chaudhary
Ankit Chaudhary

πŸ’»
samz
samz

πŸ’»
Bhaswati Roy
Bhaswati Roy

πŸ“–
AISHAT MUIBUDEEN
AISHAT MUIBUDEEN

🎨
Nawed Ali
Nawed Ali

πŸ’»
Olaleye Blessing
Olaleye Blessing

πŸ’» ️️️️♿️
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! diff --git a/assets/docs/fragments/cli-installation.md b/assets/docs/fragments/cli-installation.md new file mode 100644 index 000000000000..67a0796c8528 --- /dev/null +++ b/assets/docs/fragments/cli-installation.md @@ -0,0 +1,62 @@ +### CLI Installation +Follow the [AsyncAPI CLI installation](https://github.com/asyncapi/cli#installation) instructions below, based on your computer’s operating system. + +
+MacOS + +`brew` +
+You can install in MacOS via brew: `brew install asyncapi`. + +`pkg` +
+Each release of CLI produces a MacOS dedicated pkg file that enables you to install this CLI as MacOS application. + +``` +# Download latest release. To download specific release, your link should look similar to https://github.com/asyncapi/cli/releases/download/v0.13.0/asyncapi.pkg. All releases are listed in https://github.com/asyncapi/cli/releases +curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.pkg +# Install AsyncAPI CLI +sudo installer -pkg asyncapi.pkg -target / +``` + +
+ +
+Linux + +You can install in Linux via `dpkg`, a debian package manager: + +1. `curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.deb` +2. `sudo dpkg -i asyncapi.deb` + +
+ +
+Other OS + +[Read further AsyncAPI CLI installation instructions for different operating systems](https://github.com/asyncapi/cli#installation). +
+ +#### Using NPM and Node.js +Alternitavely, you can install the [AsyncAPI CLI](https://github.com/asyncapi/cli#installation) with Node.js `>=v10` and [NPM](https://nodejs.org/en/download/package-manager/). + +
+Install CLI globally + +Install AsyncAPI CLI _globally_ with the following command: + +``` +npm install -g @asyncapi/cli +``` +
+ +
+Install specific CLI version + +To install a specific version of the AsyncAPI CLI, pass the `verion` during installation: + +``` +npm install -g @asyncapi/cli@{version} +``` + +
diff --git a/components/AlgoliaSearch.js b/components/AlgoliaSearch.js new file mode 100644 index 000000000000..c71aea80bae2 --- /dev/null +++ b/components/AlgoliaSearch.js @@ -0,0 +1,237 @@ +import { useState, useEffect, useCallback, useRef, createContext, useContext } from 'react' +import { createPortal } from 'react-dom' +import { useRouter } from 'next/router' +import Link from 'next/link' +import Head from 'next/head' +import { DocSearchModal } from '@docsearch/react' +import clsx from 'clsx' + +export const INDEX_NAME = 'asyncapi'; +export const DOCS_INDEX_NAME = 'asyncapi-docs'; +const APP_ID = 'Z621OGRI9Y'; +const API_KEY = '5a4122ae46ce865146d23d3530595d38'; + +const SearchContext = createContext() + +export default function AlgoliaSearch({ children }) { + const [isOpen, setIsOpen] = useState(false); + const [indexName, setIndexName] = useState(INDEX_NAME); + const [initialQuery, setInitialQuery] = useState(null); + + const onOpen = useCallback((_indexName) => { + _indexName && setIndexName(_indexName); + setIsOpen(true) + }, [setIsOpen, setIndexName]); + + const onClose = useCallback(() => { + setIsOpen(false); + }, [setIsOpen]); + + const onInput = useCallback( + (e) => { + setIsOpen(true) + setInitialQuery(e.key) + }, + [setIsOpen, setInitialQuery] + ); + + useDocSearchKeyboardEvents({ + isOpen, + onOpen, + onClose, + onInput, + }); + + return ( + <> + + + + + {children} + + {isOpen && } + + ); +} + +function AlgoliaModal({ onClose, initialQuery, indexName }) { + const router = useRouter(); + + return createPortal( + { + return `https://github.com/asyncapi/website/issues/new?title=Cannot%20search%20given%20query:%20${query}`; + }} + />, + document.body, + ); +} + +function Hit({ hit, children }) { + return ( + + + {children} + + + ) +} + +function useDocSearchKeyboardEvents({ isOpen, onOpen, onClose }) { + useEffect(() => { + function onKeyDown(event) { + if ( + (event.keyCode === 27 && isOpen) || + (event.key === 'k' && (event.metaKey || event.ctrlKey)) || + (!isEditingContent(event) && event.key === '/' && !isOpen) + ) { + event.preventDefault(); + + if (isOpen) { + onClose() + } else if (!document.body.classList.contains('DocSearch--active')) { + let indexName = INDEX_NAME; + if (typeof document !== 'undefined') { + const loc = document.location; + indexName = loc.pathname.startsWith('/docs') ? DOCS_INDEX_NAME : INDEX_NAME; + } + onOpen(indexName) + } + } + } + + window.addEventListener('keydown', onKeyDown) + return () => { + window.removeEventListener('keydown', onKeyDown) + } + }, [isOpen, onOpen, onClose]); +} + +export function SearchButton({ children, indexName = INDEX_NAME, ...props }) { + const { onOpen, onInput } = useContext(SearchContext); + const searchButtonRef = useRef(); + const actionKey = getActionKey(); + + useEffect(() => { + function onKeyDown(event) { + if (searchButtonRef && searchButtonRef.current === document.activeElement && onInput) { + if (/[a-zA-Z0-9]/.test(String.fromCharCode(event.keyCode))) { + onInput(event) + } + } + } + + window.addEventListener('keydown', onKeyDown) + return () => { + window.removeEventListener('keydown', onKeyDown) + } + }, [onInput, searchButtonRef]); + + return ( + + ); +} + +function isEditingContent(event) { + const element = event.target; + const tagName = element.tagName; + + return ( + element.isContentEditable || + tagName === 'INPUT' || + tagName === 'SELECT' || + tagName === 'TEXTAREA' + ) +} + +function getActionKey() { + if (typeof navigator !== 'undefined') { + if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.userAgentData?.platform || navigator.platform)) { + return { + shortKey: '⌘', + key: 'Command', + } + } + return { + shortKey: 'Ctrl', + key: 'Control', + } + } +} + +function transformItems(items) { + return items.map((item, index) => { + // We transform the absolute URL into a relative URL to + // leverage Next's preloading. + const a = document.createElement('a') + a.href = item.url + + const hash = a.hash === '#content-wrapper' || a.hash === '#header' ? '' : a.hash + + if (item.hierarchy?.lvl0) { + item.hierarchy.lvl0 = item.hierarchy.lvl0.replace(/&/g, '&') + } + + if (item._highlightResult?.hierarchy?.lvl0?.value) { + item._highlightResult.hierarchy.lvl0.value = + item._highlightResult.hierarchy.lvl0.value.replace(/&/g, '&') + } + + return { + ...item, + url: `${a.pathname}${hash}`, + __is_result: () => true, + __is_parent: () => item.type === 'lvl1' && items.length > 1 && index === 0, + __is_child: () => + item.type !== 'lvl1' && + items.length > 1 && + items[0].type === 'lvl1' && + index !== 0, + __is_first: () => index === 1, + __is_last: () => index === items.length - 1 && index !== 0, + } + }); +} \ No newline at end of file diff --git a/components/AsyncAPILogo.js b/components/AsyncAPILogo.js index 11ed5e15787b..2604c5d65d7b 100644 --- a/components/AsyncAPILogo.js +++ b/components/AsyncAPILogo.js @@ -1,29 +1,59 @@ -export default function AsyncAPILogo ({ className }) { +export default function AsyncAPILogo({ className }) { return ( - - - - - - - + + AsyncAPI Logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) -} \ No newline at end of file +} diff --git a/components/AsyncAPILogoLight.js b/components/AsyncAPILogoLight.js new file mode 100644 index 000000000000..678fd6a59e5d --- /dev/null +++ b/components/AsyncAPILogoLight.js @@ -0,0 +1,59 @@ +export default function AsyncAPILogoLight({ className='' }) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) + } \ No newline at end of file diff --git a/components/AuthorAvatars.js b/components/AuthorAvatars.js index c45d86a80628..c3e740ff2129 100644 --- a/components/AuthorAvatars.js +++ b/components/AuthorAvatars.js @@ -1,12 +1,15 @@ export default function AuthorAvatars({ authors = [] }) { return ( - authors.map((author, index) => ( - { + let avatar = 0 ? `absolute left-${index * 7} top-0` : `relative mr-${(authors.length - 1) * 7}`} z-${(authors.length - 1 - index) * 10} h-10 w-10 border-2 border-white rounded-full object-cover hover:z-50`} src={author.photo} + loading="lazy" /> - )) + + return author.link ? {avatar} : {avatar} + }) ) } \ No newline at end of file diff --git a/components/Calendar.js b/components/Calendar.js index a9f25a9068ce..0a1388d2ccc2 100644 --- a/components/Calendar.js +++ b/components/Calendar.js @@ -1,40 +1,56 @@ -import moment from 'moment' - -export default function Calendar ({ className = '' }) { - const referenceDate = moment.utc('2020-06-09T08:00:00') - - function toggleMorningAfternoon(morningOrAfternoon) { - return morningOrAfternoon === 'morning' ? 'afternoon' : 'morning' - } - - function upcomingEvents() { - let nextDate = referenceDate - let morningOrAfternoon = 'morning' - - do { - morningOrAfternoon = toggleMorningAfternoon(morningOrAfternoon) - nextDate.add(14, 'days').hours(morningOrAfternoon === 'morning' ? 8 : 16) - } while(nextDate.isBefore()) - - return [ - nextDate.hours(morningOrAfternoon === 'morning' ? 8 : 16), - moment(nextDate).add(14, 'days').hours(morningOrAfternoon === 'morning' ? 16 : 8), - ] - } +import eventsData from '../config/meetings.json'; +import GoogleCalendarButton from './buttons/GoogleCalendarButton'; +import Heading from './typography/Heading'; +import { getEvents } from '../lib/staticHelpers'; +export default function Calendar({ className = '', size, text="text-left" }) { + const CALENDAR_URL = + 'https://calendar.google.com/calendar/embed?src=c_q9tseiglomdsj6njuhvbpts11c%40group.calendar.google.com&ctz=UTC'; + const eventsExist = eventsData.length > 0; return ( -
-

Upcoming events

- { - upcomingEvents().map((event, index) => ( -
-
- {event.local().format('D')} -
-
{event.local().format('LLLL')} UTC{event.local().format('Z')}
-
- )) +
+ + Upcoming events + + + {eventsExist ? +
+ +
+ : +
+ There are no meetings scheduled for next few days. +
}
- ) -} \ No newline at end of file + ); +} diff --git a/components/CaseStudyCard.js b/components/CaseStudyCard.js new file mode 100644 index 000000000000..fc741b4c487b --- /dev/null +++ b/components/CaseStudyCard.js @@ -0,0 +1,29 @@ +import Paragraph from './typography/Paragraph'; + +export default function CaseStudyCard({ + studies = [] +}) { + if(studies.length === 0){ + return null; + } + return ( +
+ {studies.map((study, index) => ( + +
+ + {study.company.name} + + + { study.company.description } + +
+
+ ))} +
+ ); +} diff --git a/components/DemoAnimation.js b/components/DemoAnimation.js index 16fb71fa5b26..107e483c6b56 100644 --- a/components/DemoAnimation.js +++ b/components/DemoAnimation.js @@ -2,7 +2,8 @@ import { useState, useEffect } from 'react' import Typing from 'react-typing-animation' import MacWindow from './MacWindow' import ArrowRight from './icons/ArrowRight' -import OpenInPlaygroundButton from './buttons/OpenInPlaygroundButton' +import OpenInStudioButton from './buttons/OpenInStudioButton' +import Heading from './typography/Heading' export default function DemoAnimation({ className = '' }) { const [started, setStarted] = useState(true) @@ -43,7 +44,7 @@ export default function DemoAnimation({ className = '' }) { const common = ( <>
- asyncapi: 2.0.0 + asyncapi: 2.6.0
info: @@ -201,7 +202,7 @@ export default function DemoAnimation({ className = '' }) { return (
-
+
setShowEmail(true)) }
-
-
-

+
+
+ Play with it! -

-

- Open this example on AsyncAPI Playground to get a better taste of the specification. No signup is required! + +

+ Open this example on AsyncAPI Studio to get a better taste of the specification. No signup is required!

- +
{ + setSubmitted(false); + setError(false); + }, [asPath]) + + const date_stamp = new Date() + const time_stamp = date_stamp.toUTCString(); + + async function handleSubmit(e) { + e.preventDefault(); + const data = { + title: `Feedback on ${asPath} - ${time_stamp}`, + feedback: feedback + } + + fetch("/.netlify/functions/github_discussions", { + method: "POST", + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json', + }, + }).then((response) => { + + if (response.status === 200) { + setSubmitted(true); + } + if(response.status !== 200) { + setError(true); + } + response.json(); + console.log(response); + }).then(data =>{ + console.log(data); + }) + } + + if (submitted) { + return ( +
+
+ +
+
+ Thank you for your feedback! +
+
+ Your contribution has been received and we couldn't be happier. +
+ +
+ + Follow on GitHub +
+
+
+ ) + } + if(error){ + return ( +
+
+ +
+
+ Oops! Something went wrong... +
+
+ We were unable to process your feedback +
+ +
+ ); + } + return ( +
+
+ +
+
+ Was this helpful? +
+
+ Help us improve the docs by adding your contribution. +
+
+
+
+
+