diff --git a/.github/workflows/lock-discussion/.gitignore b/.github/workflows/lock-discussion/.gitignore new file mode 100644 index 0000000000..52f06264e1 --- /dev/null +++ b/.github/workflows/lock-discussion/.gitignore @@ -0,0 +1,12 @@ +node_modules + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.github/workflows/lock-discussion/index.mjs b/.github/workflows/lock-discussion/index.mjs new file mode 100644 index 0000000000..f5f9e2a595 --- /dev/null +++ b/.github/workflows/lock-discussion/index.mjs @@ -0,0 +1,100 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +//import fetch from "node-fetch"; +import { graphql } from "@octokit/graphql" +//global.fetch = fetch; + +const graphqlWithAuth = graphql.defaults({ + headers: { + authorization: process.env.TOKEN, + }, +}); + +async function lockDiscussions(ids) { + for (let discussionId of ids) { + try { + await graphqlWithAuth( + ` + mutation lock ($id: ID!) { + lockLockable(input:{lockableId: $id}) { + clientMutationId + } + } + `, + { + id: discussionId, + } + ); + } catch (e) { + console.log(e); + } + } +} + +async function main () { + const unlockedNodes = [] + const oneDay = 1000 * 60 * 60 * 24; // one day in ms + const today = new Date(); + let readDiscussions = true + let cursor = null + while (readDiscussions) { + const {repository} = await graphqlWithAuth(` + query discussionListQuery ($owner: String!, $repo: String!, $lastId: String) { + repository(owner:$owner, name:$repo) { + discussions(states:[OPEN], first:4, after: $lastId) { + totalCount + nodes { + id + answerChosenAt + createdAt + updatedAt + locked + title + category { + name + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + } + `, { + owner: "cloudscape-design", + repo: "components", + lastId: cursor, + }); + + repository.discussions.nodes.forEach(discussion => { + if (!discussion.locked) { + const isQA = discussion.category.name === 'Q&A' + const lockQA = !!discussion.answerChosenAt + && (today - new Date(discussion.answerChosenAt).getTime()) / oneDay > 7 + + // there is no reliable way to detect if it was answered, + // so we give it 2 weeks + const lockGeneral = !!discussion.updatedAt + && discussion.updatedAt !== discussion.createdAt + && (today - new Date(discussion.updatedAt).getTime()) / oneDay > 14 + + const shouldBeLocked = isQA ? lockQA : lockGeneral; + if (shouldBeLocked) { + unlockedNodes.push(discussion.id) + } + } + }) + const {endCursor, hasNextPage} = repository.discussions.pageInfo; + readDiscussions = hasNextPage + cursor = endCursor + } + + console.log(`Discussions to lock: ${unlockedNodes.length}`); + if (unlockedNodes.length) { + await lockDiscussions(unlockedNodes); + } + console.log('Locking completed'); +} + +main(); \ No newline at end of file diff --git a/.github/workflows/lock-discussion/package.json b/.github/workflows/lock-discussion/package.json new file mode 100644 index 0000000000..7a85394fc3 --- /dev/null +++ b/.github/workflows/lock-discussion/package.json @@ -0,0 +1,18 @@ +{ + "name": "lock-discussion", + "version": "1.0.0", + "description": "", + "main": "index.mjs", + "type": "module", + "scripts": { + "lock": "node index.mjs $TOKEN" + }, + "repository": { + "type": "git", + "url": "https://github.com/cloudscape-design/actions.git" + }, + "private": true, + "dependencies": { + "@octokit/graphql": "^7.0.2" + } +} diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml new file mode 100644 index 0000000000..7f79846c97 --- /dev/null +++ b/.github/workflows/lock.yml @@ -0,0 +1,29 @@ +name: Lock threads + + +on: + schedule: + - cron: '0 0 * * 1' + + workflow_dispatch: + pull_request: + branches: + - main + +permissions: + discussions: write + +jobs: + lock-discussion: + runs-on: ubuntu-latest + steps: + - name: Setup lock-discussion project + run: | + cp -r components/.github/workflows/lock-discussion lock-discussion + cd lock-discussion + npm i --force + + - name: Run lock discussion + run: | + cd lock-discussion + npm run lock --TOKEN=${{ secrets.GITHUB_TOKEN }} \ No newline at end of file