diff --git a/.github/workflows/add-good-first-issue-labels.yml b/.github/workflows/add-good-first-issue-labels.yml index 05d05caf..5ba7a6a8 100644 --- a/.github/workflows/add-good-first-issue-labels.yml +++ b/.github/workflows/add-good-first-issue-labels.yml @@ -9,15 +9,20 @@ on: types: - created +permissions: {} + jobs: add-labels: + name: Add 'Good First Issue' and 'area/*' 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 + permissions: + issues: write # This is needed to add labels to issues. steps: - name: Add label uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | const areas = ['javascript', 'typescript', 'java' , 'go', 'docs', 'ci-cd', 'design']; const words = context.payload.comment.body.trim().split(" "); 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 index 2db55d85..99078d37 100644 --- 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 @@ -12,8 +12,15 @@ on: types: - created +permissions: {} + jobs: add-ready-to-merge-label: + name: Add ready-to-merge label + permissions: + issues: write # required to add labels and post comments on PR issues + pull-requests: write # required to read PR metadata from the issue pull_request URL + contents: read # required to compare PR branch commits against base if: > github.event.issue.pull_request && github.event.issue.state != 'closed' && @@ -30,7 +37,7 @@ jobs: env: GITHUB_ACTOR: ${{ github.actor }} with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | const prDetailsUrl = context.payload.issue.pull_request.url; const { data: pull } = await github.request(prDetailsUrl); @@ -69,6 +76,10 @@ jobs: } add-do-not-merge-label: + name: Add do-not-merge label + permissions: + issues: write # required to add labels on PR issues + pull-requests: write # required to read PR metadata from the issue pull_request URL if: > github.event.issue.pull_request && github.event.issue.state != 'closed' && @@ -82,7 +93,7 @@ jobs: - name: Add do-not-merge label uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | github.rest.issues.addLabels({ issue_number: context.issue.number, @@ -91,6 +102,10 @@ jobs: labels: ['do-not-merge'] }) add-autoupdate-label: + name: Add autoupdate label + permissions: + issues: write # required to add labels on PR issues + pull-requests: write # required to read PR metadata from the issue pull_request URL if: > github.event.issue.pull_request && github.event.issue.state != 'closed' && @@ -104,7 +119,7 @@ jobs: - name: Add autoupdate label uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | github.rest.issues.addLabels({ issue_number: context.issue.number, diff --git a/.github/workflows/automerge-for-humans-merging.yml b/.github/workflows/automerge-for-humans-merging.yml index 482c83d7..b47a551b 100644 --- a/.github/workflows/automerge-for-humans-merging.yml +++ b/.github/workflows/automerge-for-humans-merging.yml @@ -14,16 +14,20 @@ on: - edited - ready_for_review - reopened - - unlocked + - unlocked # zizmor: ignore[dangerous-triggers] needed if we want author to be our bot + +permissions: {} jobs: automerge-for-humans: + name: Automerge PRs labeled with ready-to-merge + permissions: + contents: read # required for PR commit metadata reads + pull-requests: read # required to read pull request details in github-script steps # it runs only if PR actor is not a bot, at least not a bot that we know 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]') + !contains(fromJSON('["asyncapi-bot","dependabot[bot]","dependabot-preview[bot]"]'), github.event.pull_request.user.login) runs-on: ubuntu-latest steps: - name: Get PR authors @@ -68,9 +72,11 @@ jobs: - name: Create commit message id: create-commit-message uses: actions/github-script@v7 + env: + AUTHORS_JSON: ${{ steps.authors.outputs.result }} with: script: | - const authors = ${{ steps.authors.outputs.result }}; + const authors = JSON.parse(process.env.AUTHORS_JSON); if (Object.keys(authors).length === 0) { core.setFailed('No authors found in the PR'); 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 index d5a290dd..d31ed820 100644 --- 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 @@ -6,19 +6,24 @@ name: Remove ready-to-merge label on: - pull_request_target: + pull_request: types: - synchronize - edited +permissions: {} + jobs: remove-ready-label: + name: Remove ready-to-merge label runs-on: ubuntu-latest + permissions: + pull-requests: write # required to remove labels and post comments on PR issues steps: - name: Remove label uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | const labelToRemove = 'ready-to-merge'; const labels = context.payload.pull_request.labels; diff --git a/.github/workflows/automerge-orphans.yml b/.github/workflows/automerge-orphans.yml index 23a0b007..cda0740e 100644 --- a/.github/workflows/automerge-orphans.yml +++ b/.github/workflows/automerge-orphans.yml @@ -7,19 +7,26 @@ on: schedule: - cron: "0 0 * * *" +permissions: {} + jobs: identify-orphans: if: startsWith(github.repository, 'asyncapi/') name: Find orphans and notify + permissions: + contents: read # required by checkout and repository metadata reads + pull-requests: read # required to list open pull requests runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Get list of orphans uses: actions/github-script@v7 id: orphans with: - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ github.token }} script: | const query = `query($owner:String!, $name:String!) { repository(owner:$owner, name:$name){ diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 9faa78b1..e81c0036 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -4,10 +4,12 @@ name: Automerge PRs from bots on: - pull_request_target: + pull_request_target: # Needed as GH_TOKEN_BOT_EVE needed for approval. types: - opened - - synchronize + - synchronize # zizmor: ignore[dangerous-triggers] + +permissions: {} jobs: autoapprove-for-bot: diff --git a/.github/workflows/autoupdate.yml b/.github/workflows/autoupdate.yml index eeb77a47..30ff788f 100644 --- a/.github/workflows/autoupdate.yml +++ b/.github/workflows/autoupdate.yml @@ -18,6 +18,8 @@ on: - 'bot/**' - 'all-contributors/**' +permissions: {} + jobs: autoupdate-for-bot: if: startsWith(github.repository, 'asyncapi/') @@ -25,7 +27,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Autoupdating - uses: docker://chinthakagodawita/autoupdate-action:v1 + uses: chinthakagodawita/autoupdate@0707656cd062a3b0cf8fa9b2cda1d1404d74437e env: GITHUB_TOKEN: '${{ secrets.GH_TOKEN_BOT_EVE }}' PR_FILTER: "labelled" diff --git a/.github/workflows/bounty-program-commands.yml b/.github/workflows/bounty-program-commands.yml index c42e3005..3447c2eb 100644 --- a/.github/workflows/bounty-program-commands.yml +++ b/.github/workflows/bounty-program-commands.yml @@ -20,10 +20,16 @@ env: {"name": "bounty", "color": "0e8a16", "description": "Participation in the Bounty Program"} ] +permissions: {} + jobs: guard-against-unauthorized-use: + name: Guard against unauthorized use + permissions: + issues: write # required to post a comment on the issue/PR + pull-requests: write # required to post a comment on the issue/PR if it's a PR if: > - github.actor != ('aeworxet' || 'thulieblack') && + !contains(fromJSON('["aeworxet","thulieblack"]'), github.actor) && ( startsWith(github.event.comment.body, '/bounty' ) ) @@ -36,7 +42,7 @@ jobs: env: ACTOR: ${{ github.actor }} with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | const commentText = `❌ @${process.env.ACTOR} is not authorized to use the Bounty Program's commands. These commands can only be used by members of the [Bounty Team](https://github.com/orgs/asyncapi/teams/bounty_team).`; @@ -50,19 +56,22 @@ jobs: }) add-label-bounty: + name: Add bounty label + permissions: + issues: write # required to read/create labels and add labels on the issue/PR + pull-requests: write # required to read/create labels and add labels on the issue/PR if: > - github.actor == ('aeworxet' || 'thulieblack') && + contains(fromJSON('["aeworxet","thulieblack"]'), github.actor) && ( startsWith(github.event.comment.body, '/bounty' ) ) runs-on: ubuntu-latest - steps: - name: Add label `bounty` uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | const BOUNTY_PROGRAM_LABELS = JSON.parse(process.env.BOUNTY_PROGRAM_LABELS_JSON); let LIST_OF_LABELS_FOR_REPO = await github.rest.issues.listLabelsForRepo({ @@ -91,19 +100,21 @@ jobs: }) remove-label-bounty: + name: Remove bounty label + permissions: + issues: write # required to read/remove labels on the issue/PR + pull-requests: write # required to read/remove labels on the issue/PR if it's a PR if: > - github.actor == ('aeworxet' || 'thulieblack') && + contains(fromJSON('["aeworxet","thulieblack"]'), github.actor) && ( startsWith(github.event.comment.body, '/unbounty' ) ) - runs-on: ubuntu-latest - steps: - name: Remove label `bounty` uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | const BOUNTY_PROGRAM_LABELS = JSON.parse(process.env.BOUNTY_PROGRAM_LABELS_JSON); let LIST_OF_LABELS_FOR_ISSUE = await github.rest.issues.listLabelsOnIssue({ diff --git a/.github/workflows/bump.yml b/.github/workflows/bump.yml index 42c08767..6c4fbbbf 100644 --- a/.github/workflows/bump.yml +++ b/.github/workflows/bump.yml @@ -13,6 +13,9 @@ on: branches: - master +permissions: + contents: read # To checkout code + jobs: bump-in-dependent-projects: name: Bump this package in repositories that depend on it @@ -21,9 +24,11 @@ jobs: steps: - name: Checkout repo uses: actions/checkout@v4 + with: + persist-credentials: false - name: Check if Node.js project and has package.json id: packagejson - run: test -e ./package.json && echo "exists=true" >> $GITHUB_OUTPUT || echo "exists=false" >> $GITHUB_OUTPUT + run: test -e ./package.json && echo "exists=true" >> "$GITHUB_OUTPUT" || echo "exists=false" >> "$GITHUB_OUTPUT" - name: Setup corepack with pnpm and yarn if: steps.packagejson.outputs.exists == 'true' run: corepack enable diff --git a/.github/workflows/help-command.yml b/.github/workflows/help-command.yml index 6228c56f..6fe1a137 100644 --- a/.github/workflows/help-command.yml +++ b/.github/workflows/help-command.yml @@ -4,21 +4,26 @@ name: Create help comment on: - issue_comment: - types: - - created + issue_comment: + types: + - created + +permissions: {} jobs: create_help_comment_pr: + name: Help Comment in PR if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/help') && github.actor != 'asyncapi-bot' }} runs-on: ubuntu-latest + permissions: + pull-requests: write # To comment on Pull requests steps: - name: Add comment to PR uses: actions/github-script@v7 env: ACTOR: ${{ github.actor }} with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.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/ @@ -41,15 +46,18 @@ jobs: }) create_help_comment_issue: + name: Help Comment in Issue if: ${{ !github.event.issue.pull_request && startsWith(github.event.comment.body, '/help') && github.actor != 'asyncapi-bot' }} runs-on: ubuntu-latest + permissions: + issues: write # To comment on Issues steps: - name: Add comment to Issue uses: actions/github-script@v7 env: ACTOR: ${{ github.actor }} with: - github-token: ${{ secrets.GH_TOKEN }} + github-token: ${{ github.token }} script: | github.rest.issues.createComment({ issue_number: context.issue.number, diff --git a/.github/workflows/if-nodejs-pr-testing.yml b/.github/workflows/if-nodejs-pr-testing.yml index 2bab0a7a..cef2b770 100644 --- a/.github/workflows/if-nodejs-pr-testing.yml +++ b/.github/workflows/if-nodejs-pr-testing.yml @@ -8,6 +8,9 @@ on: pull_request: types: [opened, reopened, synchronize, ready_for_review] +permissions: + contents: read + jobs: test-nodejs-pr: name: Test NodeJS PR - ${{ matrix.os }} @@ -18,21 +21,21 @@ jobs: steps: - if: > !github.event.pull_request.draft && !( - (github.actor == 'asyncapi-bot' && ( + (github.event.pull_request.user.login == 'asyncapi-bot' && ( startsWith(github.event.pull_request.title, 'ci: update of files from global .github repo') || startsWith(github.event.pull_request.title, 'chore(release):') )) || - (github.actor == 'asyncapi-bot-eve' && ( + (github.event.pull_request.user.login == 'asyncapi-bot-eve' && ( startsWith(github.event.pull_request.title, 'ci: update of files from global .github repo') || startsWith(github.event.pull_request.title, 'chore(release):') )) || - (github.actor == 'allcontributors[bot]' && + (github.event.pull_request.user.login == 'allcontributors[bot]' && startsWith(github.event.pull_request.title, 'docs: add') ) ) id: should_run name: Should Run - run: echo "shouldrun=true" >> $GITHUB_OUTPUT + run: echo "shouldrun=true" >> "$GITHUB_OUTPUT" shell: bash - if: steps.should_run.outputs.shouldrun == 'true' name: Set git to use LF #to once and for all finish neverending fight between Unix and Windows @@ -43,10 +46,12 @@ jobs: - if: steps.should_run.outputs.shouldrun == 'true' name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - if: steps.should_run.outputs.shouldrun == 'true' name: Check if Node.js project and has package.json id: packagejson - run: test -e ./package.json && echo "exists=true" >> $GITHUB_OUTPUT || echo "exists=false" >> $GITHUB_OUTPUT + run: test -e ./package.json && echo "exists=true" >> "$GITHUB_OUTPUT" || echo "exists=false" >> "$GITHUB_OUTPUT" shell: bash - if: steps.packagejson.outputs.exists == 'true' name: Determine what node version to use diff --git a/.github/workflows/if-nodejs-release.yml b/.github/workflows/if-nodejs-release.yml index 462b5f41..8eac0746 100644 --- a/.github/workflows/if-nodejs-release.yml +++ b/.github/workflows/if-nodejs-release.yml @@ -18,13 +18,9 @@ on: - next permissions: - contents: write # to be able to publish a GitHub release - issues: write # to be able to comment on released issues - pull-requests: write # to be able to comment on released pull requests - id-token: write # to enable use of OIDC for trusted publishing and npm provenance + contents: read jobs: - test-nodejs: # We just check the message of first commit as there is always just one commit because we squash into one before merging # "commits" contains array of objects where one of the properties is commit "message" @@ -48,9 +44,11 @@ jobs: shell: bash - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Check if Node.js project and has package.json id: packagejson - run: test -e ./package.json && echo "exists=true" >> $GITHUB_OUTPUT || echo "exists=false" >> $GITHUB_OUTPUT + run: test -e ./package.json && echo "exists=true" >> "$GITHUB_OUTPUT" || echo "exists=false" >> "$GITHUB_OUTPUT" shell: bash - if: steps.packagejson.outputs.exists == 'true' name: Determine what node version to use @@ -90,6 +88,11 @@ jobs: needs: [test-nodejs] name: Publish to any of NPM, Github, or Docker Hub runs-on: ubuntu-latest + permissions: + contents: write # to be able to publish a GitHub release + issues: write # to be able to comment on released issues + pull-requests: write # to be able to comment on released pull requests + id-token: write # to enable use of OIDC for trusted publishing and npm provenance steps: - name: Set git to use LF #to once and for all finish neverending fight between Unix and Windows run: | @@ -97,9 +100,11 @@ jobs: git config --global core.eol lf - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Check if Node.js project and has package.json id: packagejson - run: test -e ./package.json && echo "exists=true" >> $GITHUB_OUTPUT || echo "exists=false" >> $GITHUB_OUTPUT + run: test -e ./package.json && echo "exists=true" >> "$GITHUB_OUTPUT" || echo "exists=false" >> "$GITHUB_OUTPUT" shell: bash - if: steps.packagejson.outputs.exists == 'true' name: Determine what node version to use diff --git a/.github/workflows/if-nodejs-version-bump.yml b/.github/workflows/if-nodejs-version-bump.yml index d038414e..ddccff27 100644 --- a/.github/workflows/if-nodejs-version-bump.yml +++ b/.github/workflows/if-nodejs-version-bump.yml @@ -9,10 +9,15 @@ on: types: - published +permissions: {} + jobs: version_bump: name: Generate assets and bump NodeJS runs-on: ubuntu-latest + permissions: + contents: write # required to create PR with bumped version in package.json + pull-requests: write # required to create PR with bumped version in package.json steps: - name: Checkout repository uses: actions/checkout@v4 @@ -21,9 +26,10 @@ jobs: # in case release is created from release branch then we need to checkout from given branch # if @semantic-release/github is used to publish, the minimum version is 7.2.0 for proper working ref: ${{ github.event.release.target_commitish }} + persist-credentials: false - name: Check if Node.js project and has package.json id: packagejson - run: test -e ./package.json && echo "exists=true" >> $GITHUB_OUTPUT || echo "exists=false" >> $GITHUB_OUTPUT + run: test -e ./package.json && echo "exists=true" >> "$GITHUB_OUTPUT" || echo "exists=false" >> "$GITHUB_OUTPUT" - if: steps.packagejson.outputs.exists == 'true' name: Determine what node version to use # This workflow is from our own org repo and safe to reference by 'master'. @@ -59,7 +65,7 @@ jobs: RELEASE_TAG: ${{github.event.release.tag_name}} RELEASE_URL: ${{github.event.release.html_url}} with: - token: ${{ secrets.GH_TOKEN }} + token: ${{ github.token }} commit-message: 'chore(release): ${{ env.RELEASE_TAG }}' committer: asyncapi-bot author: asyncapi-bot diff --git a/.github/workflows/issues-prs-notifications.yml b/.github/workflows/issues-prs-notifications.yml index ce136286..1e3b616e 100644 --- a/.github/workflows/issues-prs-notifications.yml +++ b/.github/workflows/issues-prs-notifications.yml @@ -9,11 +9,13 @@ on: types: [opened, reopened] pull_request_target: - types: [opened, reopened, ready_for_review] + types: [opened, reopened, ready_for_review] # zizmor: ignore[dangerous-triggers] discussion: types: [created] +permissions: {} + jobs: issue: if: github.event_name == 'issues' && github.actor != 'asyncapi-bot' && github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]' diff --git a/.github/workflows/lint-pr-title.yml b/.github/workflows/lint-pr-title.yml index 77aa1c6e..106f3166 100644 --- a/.github/workflows/lint-pr-title.yml +++ b/.github/workflows/lint-pr-title.yml @@ -4,32 +4,37 @@ name: Lint PR title on: - pull_request_target: + pull_request: types: [opened, reopened, synchronize, edited, ready_for_review] +permissions: {} + jobs: lint-pr-title: name: Lint PR title runs-on: ubuntu-latest + permissions: + contents: read # To checkout code and read PR information + pull-requests: write # To comment on PR if the title is not valid 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) }} + - if: ${{ !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor) }} # zizmor: ignore[obfuscation] 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: ${{ github.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)}} + - if: ${{ always() && steps.lint_pr_title.outputs.error_message != null && !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor)}} # zizmor: ignore[obfuscation] 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}} + GITHUB_TOKEN: ${{ github.token }} message: | We require all PRs to follow [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/). @@ -44,4 +49,4 @@ jobs: with: header: pr-title-lint-error delete: true - GITHUB_TOKEN: ${{ secrets.GH_TOKEN}} + GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/microgrant-program-commands.yml b/.github/workflows/microgrant-program-commands.yml new file mode 100644 index 00000000..9eadd748 --- /dev/null +++ b/.github/workflows/microgrant-program-commands.yml @@ -0,0 +1,137 @@ +# This workflow is centrally managed at https://github.com/asyncapi/.github/ +# Don't make changes to this file in this repository, as they will be overwritten with +# changes made to the same file in the abovementioned repository. + +# The purpose of this workflow is to allow Microgrant Team members +# (https://github.com/orgs/asyncapi/teams/microgrant_team) to issue commands to the +# organization's global AsyncAPI bot related to the Microgrant Program, while at the +# same time preventing unauthorized users from misusing them. + +name: Microgrant Program commands + +on: + issue_comment: + types: + - created + +env: + MICROGRANT_PROGRAM_LABELS_JSON: | + [ + {"name": "microgrant", "color": "708090", "description": "Participation in the Microgrant Program"} + ] + +permissions: {} + +jobs: + guard-against-unauthorized-use: + name: Guard against unauthorized use + permissions: + issues: write # required to post a comment on the issue/PR + pull-requests: write # required to post a comment on the issue/PR if it's a PR + if: > + !contains(fromJSON('["aeworxet","thulieblack"]'), github.actor) && + github.event.comment && + ( + github.event.comment.body == '/microgrant' || github.event.comment.body == '/unmicrogrant' + ) + + runs-on: ubuntu-latest + + steps: + - name: ❌ @${{github.actor}} made an unauthorized attempt to use a Microgrant Program's command + uses: actions/github-script@v7 + env: + ACTOR: ${{ github.actor }} + with: + github-token: ${{ github.token }} + script: | + const commentText = `❌ @${process.env.ACTOR} is not authorized to use the Microgrant Program's commands. + These commands can only be used by members of the [Microgrant Team](https://github.com/orgs/asyncapi/teams/microgrant_team).`; + + console.log(`❌ @${process.env.ACTOR} made an unauthorized attempt to use a Microgrant Program's command.`); + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: commentText + }) + + add-label-microgrant: + name: Add microgrant label + permissions: + issues: write # required to read/create labels and add labels on the issue/PR + pull-requests: write # required to read/create labels and add labels on the issue/PR + if: > + contains(fromJSON('["aeworxet","thulieblack"]'), github.actor) && + ( + github.event.comment.body == '/microgrant' + ) + + runs-on: ubuntu-latest + steps: + - name: Add label `microgrant` + uses: actions/github-script@v7 + with: + github-token: ${{ github.token }} + script: | + const MICROGRANT_PROGRAM_LABELS = JSON.parse(process.env.MICROGRANT_PROGRAM_LABELS_JSON); + let LIST_OF_LABELS_FOR_REPO = await github.rest.issues.listLabelsForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + }); + + LIST_OF_LABELS_FOR_REPO = LIST_OF_LABELS_FOR_REPO.data.map(key => key.name); + + if (!LIST_OF_LABELS_FOR_REPO.includes(MICROGRANT_PROGRAM_LABELS[0].name)) { + await github.rest.issues.createLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: MICROGRANT_PROGRAM_LABELS[0].name, + color: MICROGRANT_PROGRAM_LABELS[0].color, + description: MICROGRANT_PROGRAM_LABELS[0].description + }); + } + + console.log('Adding label `microgrant`...'); + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: [MICROGRANT_PROGRAM_LABELS[0].name] + }) + + remove-label-microgrant: + name: Remove microgrant label + permissions: + issues: write # required to read/remove labels on the issue/PR + pull-requests: write # required to read/remove labels on the issue/PR if it's a PR + if: > + contains(fromJSON('["aeworxet","thulieblack"]'), github.actor) && + ( + github.event.comment.body == '/unmicrogrant' + ) + runs-on: ubuntu-latest + steps: + - name: Remove label `microgrant` + uses: actions/github-script@v7 + with: + github-token: ${{ github.token }} + script: | + const MICROGRANT_PROGRAM_LABELS = JSON.parse(process.env.MICROGRANT_PROGRAM_LABELS_JSON); + let LIST_OF_LABELS_FOR_ISSUE = await github.rest.issues.listLabelsOnIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + LIST_OF_LABELS_FOR_ISSUE = LIST_OF_LABELS_FOR_ISSUE.data.map(key => key.name); + + if (LIST_OF_LABELS_FOR_ISSUE.includes(MICROGRANT_PROGRAM_LABELS[0].name)) { + console.log('Removing label `microgrant`...'); + github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: [MICROGRANT_PROGRAM_LABELS[0].name] + }) + } diff --git a/.github/workflows/notify-tsc-members-mention.yml b/.github/workflows/notify-tsc-members-mention.yml index ffa39bbc..d5a945a0 100644 --- a/.github/workflows/notify-tsc-members-mention.yml +++ b/.github/workflows/notify-tsc-members-mention.yml @@ -17,14 +17,16 @@ on: types: - opened - pull_request_target: + pull_request_target: # Needed to access secrets. The checkout is done on base branch so script cannot be malicious. types: - - opened - + - opened # zizmor: ignore[dangerous-triggers] discussion: types: - created +permissions: + contents: read # To checkout repository + jobs: issue: if: github.event_name == 'issues' && contains(github.event.issue.body, '@asyncapi/tsc_members') @@ -33,10 +35,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 cache: 'npm' cache-dependency-path: '**/package-lock.json' ######### @@ -56,22 +60,22 @@ jobs: SLACK_MESSAGE: ${{steps.issuemarkdown.outputs.text}} MSG_MINIMAL: true ######### - # Handling Mailchimp notifications + # Handling Kit.com notifications ######### - name: Install deps run: npm install - working-directory: ./.github/workflows/scripts/mailchimp - - name: Send email with MailChimp + working-directory: ./.github/workflows/scripts/kit + - name: Send email with Kit.com uses: actions/github-script@v7 env: - CALENDAR_ID: ${{ secrets.CALENDAR_ID }} - CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} - MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + KIT_API_KEY: ${{ secrets.KIT_API_KEY }} + KIT_TSC_TAG_ID: ${{ secrets.KIT_TSC_TAG_ID }} TITLE: ${{ github.event.issue.title }} + HTML_URL: ${{ github.event.issue.html_url }} with: script: | - const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); - sendEmail('${{github.event.issue.html_url}}', process.env.TITLE); + const sendEmail = require('./.github/workflows/scripts/kit/index.js'); + return sendEmail(process.env.HTML_URL, process.env.TITLE); pull_request: if: github.event_name == 'pull_request_target' && contains(github.event.pull_request.body, '@asyncapi/tsc_members') @@ -80,10 +84,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 cache: 'npm' cache-dependency-path: '**/package-lock.json' ######### @@ -103,22 +109,22 @@ jobs: SLACK_MESSAGE: ${{steps.prmarkdown.outputs.text}} MSG_MINIMAL: true ######### - # Handling Mailchimp notifications + # Handling Kit.com notifications ######### - name: Install deps run: npm install - working-directory: ./.github/workflows/scripts/mailchimp - - name: Send email with MailChimp + working-directory: ./.github/workflows/scripts/kit + - name: Send email with Kit.com uses: actions/github-script@v7 env: - CALENDAR_ID: ${{ secrets.CALENDAR_ID }} - CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} - MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + KIT_API_KEY: ${{ secrets.KIT_API_KEY }} + KIT_TSC_TAG_ID: ${{ secrets.KIT_TSC_TAG_ID }} TITLE: ${{ github.event.pull_request.title }} + HTML_URL: ${{ github.event.pull_request.html_url }} with: script: | - const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); - sendEmail('${{github.event.pull_request.html_url}}', process.env.TITLE); + const sendEmail = require('./.github/workflows/scripts/kit/index.js'); + return sendEmail(process.env.HTML_URL, process.env.TITLE); discussion: if: github.event_name == 'discussion' && contains(github.event.discussion.body, '@asyncapi/tsc_members') @@ -127,10 +133,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 cache: 'npm' cache-dependency-path: '**/package-lock.json' ######### @@ -142,7 +150,7 @@ jobs: id: discussionmarkdown with: markdown: "[${{github.event.discussion.title}}](${{github.event.discussion.html_url}}) \n ${{github.event.discussion.body}}" - - name: Send info about pull request + - name: Send info about discussion uses: rtCamp/action-slack-notify@c33737706dea87cd7784c687dadc9adf1be59990 # Using v2.3.2 env: SLACK_WEBHOOK: ${{secrets.SLACK_TSC_MEMBERS_NOTIFY}} @@ -150,22 +158,22 @@ jobs: SLACK_MESSAGE: ${{steps.discussionmarkdown.outputs.text}} MSG_MINIMAL: true ######### - # Handling Mailchimp notifications + # Handling Kit.com notifications ######### - name: Install deps run: npm install - working-directory: ./.github/workflows/scripts/mailchimp - - name: Send email with MailChimp + working-directory: ./.github/workflows/scripts/kit + - name: Send email with Kit.com uses: actions/github-script@v7 env: - CALENDAR_ID: ${{ secrets.CALENDAR_ID }} - CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} - MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + KIT_API_KEY: ${{ secrets.KIT_API_KEY }} + KIT_TSC_TAG_ID: ${{ secrets.KIT_TSC_TAG_ID }} TITLE: ${{ github.event.discussion.title }} + HTML_URL: ${{ github.event.discussion.html_url }} with: script: | - const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); - sendEmail('${{github.event.discussion.html_url}}', process.env.TITLE); + const sendEmail = require('./.github/workflows/scripts/kit/index.js'); + return sendEmail(process.env.HTML_URL, process.env.TITLE); issue_comment: if: ${{ github.event_name == 'issue_comment' && !github.event.issue.pull_request && contains(github.event.comment.body, '@asyncapi/tsc_members') }} @@ -174,10 +182,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 cache: 'npm' cache-dependency-path: '**/package-lock.json' ######### @@ -197,22 +207,22 @@ jobs: SLACK_MESSAGE: ${{steps.issuemarkdown.outputs.text}} MSG_MINIMAL: true ######### - # Handling Mailchimp notifications + # Handling Kit.com notifications ######### - name: Install deps run: npm install - working-directory: ./.github/workflows/scripts/mailchimp - - name: Send email with MailChimp + working-directory: ./.github/workflows/scripts/kit + - name: Send email with Kit.com uses: actions/github-script@v7 env: - CALENDAR_ID: ${{ secrets.CALENDAR_ID }} - CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} - MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + KIT_API_KEY: ${{ secrets.KIT_API_KEY }} + KIT_TSC_TAG_ID: ${{ secrets.KIT_TSC_TAG_ID }} TITLE: ${{ github.event.issue.title }} + HTML_URL: ${{ github.event.comment.html_url }} with: script: | - const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); - sendEmail('${{github.event.comment.html_url}}', process.env.TITLE); + const sendEmail = require('./.github/workflows/scripts/kit/index.js'); + return sendEmail(process.env.HTML_URL, process.env.TITLE); pr_comment: if: github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '@asyncapi/tsc_members') @@ -221,10 +231,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 cache: 'npm' cache-dependency-path: '**/package-lock.json' ######### @@ -244,22 +256,22 @@ jobs: SLACK_MESSAGE: ${{steps.prmarkdown.outputs.text}} MSG_MINIMAL: true ######### - # Handling Mailchimp notifications + # Handling Kit.com notifications ######### - name: Install deps run: npm install - working-directory: ./.github/workflows/scripts/mailchimp - - name: Send email with MailChimp + working-directory: ./.github/workflows/scripts/kit + - name: Send email with Kit.com uses: actions/github-script@v7 env: - CALENDAR_ID: ${{ secrets.CALENDAR_ID }} - CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} - MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + KIT_API_KEY: ${{ secrets.KIT_API_KEY }} + KIT_TSC_TAG_ID: ${{ secrets.KIT_TSC_TAG_ID }} TITLE: ${{ github.event.issue.title }} + HTML_URL: ${{ github.event.comment.html_url }} with: script: | - const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); - sendEmail('${{github.event.comment.html_url}}', process.env.TITLE); + const sendEmail = require('./.github/workflows/scripts/kit/index.js'); + return sendEmail(process.env.HTML_URL, process.env.TITLE); discussion_comment: if: github.event_name == 'discussion_comment' && contains(github.event.comment.body, '@asyncapi/tsc_members') @@ -268,10 +280,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 cache: 'npm' cache-dependency-path: '**/package-lock.json' ######### @@ -291,19 +305,19 @@ jobs: SLACK_MESSAGE: ${{steps.discussionmarkdown.outputs.text}} MSG_MINIMAL: true ######### - # Handling Mailchimp notifications + # Handling Kit.com notifications ######### - name: Install deps run: npm install - working-directory: ./.github/workflows/scripts/mailchimp - - name: Send email with MailChimp + working-directory: ./.github/workflows/scripts/kit + - name: Send email with Kit.com uses: actions/github-script@v7 env: - CALENDAR_ID: ${{ secrets.CALENDAR_ID }} - CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} - MAILCHIMP_API_KEY: ${{ secrets.MAILCHIMP_API_KEY }} + KIT_API_KEY: ${{ secrets.KIT_API_KEY }} + KIT_TSC_TAG_ID: ${{ secrets.KIT_TSC_TAG_ID }} TITLE: ${{ github.event.discussion.title }} + HTML_URL: ${{ github.event.comment.html_url }} with: script: | - const sendEmail = require('./.github/workflows/scripts/mailchimp/index.js'); - sendEmail('${{github.event.comment.html_url}}', process.env.TITLE); + const sendEmail = require('./.github/workflows/scripts/kit/index.js'); + return sendEmail(process.env.HTML_URL, process.env.TITLE); diff --git a/.github/workflows/please-take-a-look-command.yml b/.github/workflows/please-take-a-look-command.yml index 84b5a262..30a6938d 100644 --- a/.github/workflows/please-take-a-look-command.yml +++ b/.github/workflows/please-take-a-look-command.yml @@ -11,6 +11,8 @@ on: issue_comment: types: [created] +permissions: {} + jobs: ping-for-attention: if: > @@ -22,6 +24,7 @@ jobs: contains(github.event.comment.body, '/ptal') || contains(github.event.comment.body, '/PTAL') ) + name: Ping code owners for attention runs-on: ubuntu-latest steps: - name: Check for Please Take a Look Command @@ -31,7 +34,7 @@ jobs: script: | const prDetailsUrl = context.payload.issue.pull_request.url; const { data: pull } = await github.request(prDetailsUrl); - const reviewers = pull.requested_reviewers.map(reviewer => reviewer.login); + const reviewers = (pull.requested_reviewers || []).map(reviewer => reviewer.login); const { data: reviews } = await github.rest.pulls.listReviews({ owner: context.repo.owner, diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 311b701f..b521d394 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -8,6 +8,9 @@ on: types: - published +permissions: + contents: read # To checkout code and read release information + jobs: slack-announce: @@ -16,6 +19,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Convert markdown to slack markdown for issue # This workflow is from our own org repo and safe to reference by 'master'. uses: asyncapi/.github/.github/actions/slackify-markdown@master # //NOSONAR @@ -42,11 +47,13 @@ jobs: steps: - name: Checkout repo uses: actions/checkout@v4 + with: + persist-credentials: false - name: Get version of last and previous release uses: actions/github-script@v7 id: versions with: - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ github.token }} script: | const query = `query($owner:String!, $name:String!) { repository(owner:$owner, name:$name){ @@ -72,12 +79,12 @@ jobs: env: PREV_VERSION: ${{steps.versions.outputs.previousver}} LAST_VERSION: ${{steps.versions.outputs.lastver}} - run: echo "type=$(npx -q -p semver-diff-cli semver-diff "$PREV_VERSION" "$LAST_VERSION")" >> $GITHUB_OUTPUT + run: echo "type=$(npx -q -p semver-diff-cli semver-diff "$PREV_VERSION" "$LAST_VERSION")" >> "$GITHUB_OUTPUT" - name: Get name of the person that is behind the newly released version id: author run: | AUTHOR_NAME=$(git log -1 --pretty=format:'%an') - printf 'name=%s\n' "$AUTHOR_NAME" >> $GITHUB_OUTPUT + printf 'name=%s\n' "$AUTHOR_NAME" >> "$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 diff --git a/.github/workflows/scripts/kit/htmlContent.js b/.github/workflows/scripts/kit/htmlContent.js new file mode 100644 index 00000000..4acb5134 --- /dev/null +++ b/.github/workflows/scripts/kit/htmlContent.js @@ -0,0 +1,510 @@ +/** + * 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 + * + * Kit.com version — greeting uses Kit Liquid (subscriber.first_name). Unsubscribe is provided by the Kit email template/footer. + */ + +/** + * Escape HTML special characters to prevent XSS + */ +function escapeHtml(text) { + if (!text) return ''; + return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +module.exports = (link, title) => { + // Sanitize inputs to prevent XSS + const safeLink = escapeHtml(link); + const safeTitle = escapeHtml(title); + + return ` + + + + + + + + ${safeTitle} + + + +
+ + + + +
+ + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + +
+ + Hey {{ subscriber.first_name | strip | default: "TSC member" }},
+
+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: ${ safeTitle }. +
+ + + +
+ + + + + + + +
+ + + + + + + + +
+ + Cheers,
+AsyncAPI Initiative +
+ + + +
+ + + + + +
+ + + + + + + + +
+ + You are receiving this email because you are subscribed to TSC Voting notifications.
+  +
+ + + +
+ + +
+
+ + +` +} \ No newline at end of file diff --git a/.github/workflows/scripts/kit/index.js b/.github/workflows/scripts/kit/index.js new file mode 100644 index 00000000..5fc67b0e --- /dev/null +++ b/.github/workflows/scripts/kit/index.js @@ -0,0 +1,62 @@ +/** + * 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 core = require('@actions/core'); +const htmlContent = require('./htmlContent.js'); + +const sanitizeLinkAndTitle = (link, title) => { + // Validate inputs to prevent injection attacks + if (!link || typeof link !== 'string' || link.length > 2000) { + return core.setFailed('Invalid link parameter'); + } + if (!title || typeof title !== 'string' || title.length > 500) { + return core.setFailed('Invalid title parameter'); + } + + let parsedLink; + try { + parsedLink = new URL(link); + } catch (error) { + return core.setFailed('Invalid link parameter'); + } + + if (parsedLink.protocol !== 'https:') { + return core.setFailed('Link must use https protocol'); + } + + // Sanitize title by removing control characters and limiting length + const sanitizedTitle = title.replace(/[\x00-\x1F\x7F]/g, '').substring(0, 250); + return { sanitizedLink: parsedLink.toString(), sanitizedTitle }; +}; + +module.exports = async (link, title) => { + const KIT_BASE = 'https://api.kit.com/v4'; + const TSC_TAG_ID = Number(process.env.KIT_TSC_TAG_ID); + + // Schedule 1 minute ahead + const sendAt = new Date(Date.now() + 60 * 1000); + + const { sanitizedLink, sanitizedTitle } = sanitizeLinkAndTitle(link, title); + + const res = await fetch(`${KIT_BASE}/broadcasts`, { + method: 'POST', + headers: { + 'X-Kit-Api-Key': process.env.KIT_API_KEY, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + subject: `TSC attention required: ${sanitizedTitle}`, + preview_text: 'Check out the latest topic that TSC members have to be aware of', + content: htmlContent(sanitizedLink, sanitizedTitle), + description: `TSC notification - ${new Date().toUTCString()}`, + public: false, + published_at: null, + send_at: sendAt.toISOString(), + subscriber_filter: [{ all: [{ type: 'tag', ids: [TSC_TAG_ID] }] }] + }) + }); + + if (!res.ok) return core.setFailed(`Failed creating broadcast: ${await res.text()}`); + core.info(`Kit.com TSC broadcast scheduled for ${sendAt.toISOString()}`); +}; diff --git a/.github/workflows/scripts/kit/package-lock.json b/.github/workflows/scripts/kit/package-lock.json new file mode 100644 index 00000000..153b6ab0 --- /dev/null +++ b/.github/workflows/scripts/kit/package-lock.json @@ -0,0 +1,41 @@ +{ + "name": "schedule-email", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "schedule-email", + "license": "Apache 2.0", + "dependencies": { + "@actions/core": "1.6.0" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + } + } +} diff --git a/.github/workflows/scripts/kit/package.json b/.github/workflows/scripts/kit/package.json new file mode 100644 index 00000000..5ad5c9eb --- /dev/null +++ b/.github/workflows/scripts/kit/package.json @@ -0,0 +1,8 @@ +{ + "name": "schedule-email", + "description": "Kit.com email broadcast script for TSC notifications. This file is centrally managed in https://github.com/asyncapi/.github/", + "license": "Apache 2.0", + "dependencies": { + "@actions/core": "1.6.0" + } +} diff --git a/.github/workflows/scripts/mailchimp/htmlContent.js b/.github/workflows/scripts/mailchimp/htmlContent.js index d132c72f..e0c8ef66 100644 --- a/.github/workflows/scripts/mailchimp/htmlContent.js +++ b/.github/workflows/scripts/mailchimp/htmlContent.js @@ -2,7 +2,24 @@ * 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 */ + +/** + * Escape HTML special characters to prevent XSS + */ +function escapeHtml(text) { + if (!text) return ''; + return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + module.exports = (link, title) => { + // Sanitize inputs to prevent XSS + const safeLink = escapeHtml(link); + const safeTitle = escapeHtml(title); return ` @@ -386,7 +403,7 @@ There is a new topic at AsyncAPI Initiative that requires Technical Steering Com
Please have a look if it is just something you need to be aware of, or maybe your vote is needed.
-Topic: ${ title }. +Topic: ${ safeTitle }. diff --git a/.github/workflows/scripts/mailchimp/index.js b/.github/workflows/scripts/mailchimp/index.js deleted file mode 100644 index 4a200c6c..00000000 --- a/.github/workflows/scripts/mailchimp/index.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * 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 deleted file mode 100644 index 7ee7d84f..00000000 --- a/.github/workflows/scripts/mailchimp/package-lock.json +++ /dev/null @@ -1,597 +0,0 @@ -{ - "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 deleted file mode 100644 index cc50e43e..00000000 --- a/.github/workflows/scripts/mailchimp/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "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/stale-issues-prs.yml b/.github/workflows/stale-issues-prs.yml index 25bee820..e76a36bc 100644 --- a/.github/workflows/stale-issues-prs.yml +++ b/.github/workflows/stale-issues-prs.yml @@ -7,15 +7,21 @@ on: schedule: - cron: "0 0 * * *" +permissions: {} + jobs: stale: if: startsWith(github.repository, 'asyncapi/') name: Mark issue or PR as stale runs-on: ubuntu-latest + permissions: + contents: read # As delete-branch is not being used + issues: write # To add comments and labels to issues + pull-requests: write # To add comments and labels to PRs steps: - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0 but pointing to commit for security reasons with: - repo-token: ${{ secrets.GITHUB_TOKEN }} + repo-token: ${{ github.token }} stale-issue-message: | This issue has been automatically marked as stale because it has not had recent activity :sleeping: diff --git a/.github/workflows/transfer-issue.yml b/.github/workflows/transfer-issue.yml deleted file mode 100644 index dbe84ca6..00000000 --- a/.github/workflows/transfer-issue.yml +++ /dev/null @@ -1,62 +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: Transfer Issues between repositories - -on: - issue_comment: - types: - - created - -permissions: - issues: write - -jobs: - transfer: - if: ${{(!github.event.issue.pull_request && github.event.issue.state != 'closed' && github.actor != 'asyncapi-bot') && (startsWith(github.event.comment.body, '/transfer-issue') || startsWith(github.event.comment.body, '/ti'))}} - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - name: Extract Input - id: extract_step - env: - COMMENT: "${{ github.event.comment.body }}" - run: | - REPO=$(echo "$COMMENT" | awk '{print $2}') - echo "repo=$REPO" >> $GITHUB_OUTPUT - - name: Check Repo - uses: actions/github-script@v7 - with: - github-token: ${{secrets.GH_TOKEN}} - script: | - const r = "${{github.repository}}" - const [owner, repo] = r.split('/') - const repoToMove = process.env.REPO_TO_MOVE - const issue_number = context.issue.number - try { - const {data} = await github.rest.repos.get({ - owner, - repo: repoToMove - }) - }catch (e) { - const body = `${repoToMove} is not a repo under ${owner}. You can only transfer issue to repos that belong to the same organization.` - await github.rest.issues.createComment({ - owner, - repo, - issue_number, - body - }) - process.exit(1) - } - env: - REPO_TO_MOVE: ${{steps.extract_step.outputs.repo}} - - name: Transfer Issue - id: transferIssue - working-directory: ./ - run: | - gh issue transfer "$ISSUE_NUMBER" "asyncapi/$REPO_NAME" - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - REPO_NAME: ${{ steps.extract_step.outputs.repo }} diff --git a/.github/workflows/update-maintainers-trigger.yaml b/.github/workflows/update-maintainers-trigger.yaml index 12fc4abe..0535e39d 100644 --- a/.github/workflows/update-maintainers-trigger.yaml +++ b/.github/workflows/update-maintainers-trigger.yaml @@ -13,6 +13,9 @@ on: - '.github/CODEOWNERS' - '.docs/CODEOWNERS' +permissions: + contents: read # Just to limit GITHUB_TOKEN as we use GH_TOKEN only + jobs: trigger-maintainers-update: name: Trigger updating MAINTAINERS.yaml because of CODEOWNERS change diff --git a/.github/workflows/update-pr.yml b/.github/workflows/update-pr.yml index 2fa19b0a..285c02d3 100644 --- a/.github/workflows/update-pr.yml +++ b/.github/workflows/update-pr.yml @@ -9,12 +9,16 @@ name: Update PR branches from fork +permissions: + contents: read + on: issue_comment: types: [created] jobs: update-pr: + name: Update the fork PR with upstream changes if: > startsWith(github.repository, 'asyncapi/') && github.event.issue.pull_request && @@ -23,12 +27,16 @@ jobs: contains(github.event.comment.body, '/u') ) runs-on: ubuntu-latest + permissions: + issues: write # Required to read PR details and post comments on the PR + pull-requests: write # Required to update the PR branch + contents: read steps: - name: Get Pull Request Details id: pr uses: actions/github-script@v7 with: - github-token: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GH_TOKEN || github.token }} previews: 'merge-info-preview' # https://docs.github.com/en/graphql/overview/schema-previews#merge-info-preview-more-detailed-information-about-a-pull-requests-merge-state-preview script: | const prNumber = context.payload.issue.number; @@ -40,7 +48,7 @@ jobs: }); // If the PR has conflicts, we don't want to update it - const updateable = ['behind', 'blocked', 'unknown', 'draft', 'clean'].includes(pr.mergeable_state); + const updateable = ['behind', 'blocked', 'unknown', 'draft', 'clean', 'unstable'].includes(pr.mergeable_state); console.log(`PR #${prNumber} is ${pr.mergeable_state} and is ${updateable ? 'updateable' : 'not updateable'}`); core.setOutput('updateable', updateable); @@ -54,8 +62,10 @@ jobs: - name: Update the Pull Request if: steps.pr.outputs.updateable == 'true' uses: actions/github-script@v7 + env: + PR_DETAILS: ${{ steps.pr.outputs.result }} with: - github-token: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GH_TOKEN || github.token }} script: | const mutation = `mutation update($input: UpdatePullRequestBranchInput!) { updatePullRequestBranch(input: $input) { @@ -65,7 +75,7 @@ jobs: } }`; - const pr_details = ${{ steps.pr.outputs.result }}; + const pr_details = JSON.parse(process.env.PR_DETAILS); try { const { data } = await github.graphql(mutation, { diff --git a/.github/workflows/welcome-first-time-contrib.yml b/.github/workflows/welcome-first-time-contrib.yml index 2614d8de..49c761b9 100644 --- a/.github/workflows/welcome-first-time-contrib.yml +++ b/.github/workflows/welcome-first-time-contrib.yml @@ -4,22 +4,30 @@ name: Welcome first time contributors on: - pull_request_target: + pull_request: types: - opened issues: types: - opened +permissions: + issues: read # Required to check if the issue is the user's first contribution + pull-requests: read # Required to check if the pull request is the user's first contribution + jobs: welcome: name: Post welcome message - if: ${{ !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor) }} + if: ${{ !contains(fromJson('["asyncapi-bot", "dependabot[bot]", "dependabot-preview[bot]", "allcontributors[bot]"]'), github.actor) }} # zizmor: ignore[obfuscation] runs-on: ubuntu-latest + permissions: + contents: read # Required to read repository data for checking if it's the user's first contribution + issues: write # Required to post welcome message on issues + pull-requests: write # Required to post welcome message on pull requests steps: - uses: actions/github-script@v7 with: - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ 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).`;