mirror of
https://gitea.com/Lydanne/issues-helper.git
synced 2025-08-19 18:25:58 +08:00
Compare commits
205 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d5f2de3db2 | ||
![]() |
254683255c | ||
![]() |
0d51d36520 | ||
![]() |
635ca07363 | ||
![]() |
36a1dd8767 | ||
![]() |
5586509e90 | ||
![]() |
ecbe084012 | ||
![]() |
596892f346 | ||
![]() |
25313a56b2 | ||
![]() |
464f817556 | ||
![]() |
f2d552d67b | ||
![]() |
b363cba6ec | ||
![]() |
f3f91e4aa4 | ||
![]() |
65840f57fe | ||
![]() |
dbeaa215cb | ||
![]() |
6a55b3a9f4 | ||
![]() |
f4eba4debf | ||
![]() |
09bc8811a0 | ||
![]() |
dfac87c369 | ||
![]() |
275328970d | ||
![]() |
d51658accd | ||
![]() |
12b5247afc | ||
![]() |
02811b26b6 | ||
![]() |
a72c4f551c | ||
![]() |
e17a3a158c | ||
![]() |
3826e864ab | ||
![]() |
1cb0eedfea | ||
![]() |
7f09991212 | ||
![]() |
cde2648b72 | ||
![]() |
405d4bd782 | ||
![]() |
dad28fdb88 | ||
![]() |
ae3f30b1ef | ||
![]() |
e348bddf55 | ||
![]() |
adce2a7049 | ||
![]() |
2b3835f42e | ||
![]() |
3cc206fdcb | ||
![]() |
293fb5e353 | ||
![]() |
982af7d1b7 | ||
![]() |
6672cf5641 | ||
![]() |
68a418a2e3 | ||
![]() |
95857edf92 | ||
![]() |
99345e5b9f | ||
![]() |
0e8eacd7fd | ||
![]() |
b9d9c9bdd8 | ||
![]() |
863fd9715c | ||
![]() |
aef41a8473 | ||
![]() |
40c49147c3 | ||
![]() |
0a220d0ec9 | ||
![]() |
d874829fb1 | ||
![]() |
44c69adcf7 | ||
![]() |
d80ee9cc3b | ||
![]() |
1eb674f153 | ||
![]() |
083acea03f | ||
![]() |
f94382051c | ||
![]() |
c626dd5ef0 | ||
![]() |
bdb9ee8890 | ||
![]() |
2b4519585f | ||
![]() |
92b9e397a9 | ||
![]() |
c6a0bf65a1 | ||
![]() |
7833b3db99 | ||
![]() |
58c8d40948 | ||
![]() |
10d7255209 | ||
![]() |
20dffb5f1d | ||
![]() |
3523cc98b0 | ||
![]() |
cca9ff3da4 | ||
![]() |
733de0e514 | ||
![]() |
25d60061fc | ||
![]() |
4826be2469 | ||
![]() |
080e9fb5e3 | ||
![]() |
fbc3b95637 | ||
![]() |
9572a973dd | ||
![]() |
dec18932cf | ||
![]() |
1a0a9f0bf6 | ||
![]() |
f6cad1ea63 | ||
![]() |
8cd9c11d81 | ||
![]() |
f060eb7f7a | ||
![]() |
f591bf2cb3 | ||
![]() |
f79ccb5f94 | ||
![]() |
a83194ca41 | ||
![]() |
c0ab13d4e8 | ||
![]() |
f3ccc454b5 | ||
![]() |
18db22e255 | ||
![]() |
2ecdeeef4a | ||
![]() |
2ebe9b3225 | ||
![]() |
87bb00f55a | ||
![]() |
69e103e931 | ||
![]() |
07f26baa4f | ||
![]() |
a4367f11ad | ||
![]() |
aa229b2b9f | ||
![]() |
f2b1cc82b6 | ||
![]() |
03531cdc76 | ||
![]() |
dc85436cff | ||
![]() |
b447d44641 | ||
![]() |
21c1ba20ab | ||
![]() |
5c1fab1ef7 | ||
![]() |
2751b8e755 | ||
![]() |
3b3e72d628 | ||
![]() |
ec5a128e11 | ||
![]() |
8482b73885 | ||
![]() |
23e8a42c18 | ||
![]() |
f83978e0ed | ||
![]() |
207593c17b | ||
![]() |
47079090b4 | ||
![]() |
33f5c9a41b | ||
![]() |
3f73e5f3b7 | ||
![]() |
dc4a7a3ca8 | ||
![]() |
f76bae5b37 | ||
![]() |
b395ad434f | ||
![]() |
b5d3740262 | ||
![]() |
c7e172c679 | ||
![]() |
7198ab8542 | ||
![]() |
eb91a70ccc | ||
![]() |
db8ab69114 | ||
![]() |
86102bcaef | ||
![]() |
c585c79a2a | ||
![]() |
b64d6e451f | ||
![]() |
d443509c47 | ||
![]() |
4b5824425d | ||
![]() |
b483519646 | ||
![]() |
4a12f7e54a | ||
![]() |
1b100be0d7 | ||
![]() |
afb2d0f2e5 | ||
![]() |
86d9dd7f1a | ||
![]() |
5891ef3922 | ||
![]() |
7a119339df | ||
![]() |
958f1760a2 | ||
![]() |
d82909b31d | ||
![]() |
89884a3a50 | ||
![]() |
1d2d39036b | ||
![]() |
a66760a95f | ||
![]() |
8abd4b29f8 | ||
![]() |
03203f3b5e | ||
![]() |
0acc9bec8c | ||
![]() |
56afcb6a23 | ||
![]() |
39ff3699d6 | ||
![]() |
efca7df548 | ||
![]() |
19c073d744 | ||
![]() |
a6a35924a4 | ||
![]() |
eb13c18a92 | ||
![]() |
d4e1fb07d0 | ||
![]() |
d2ccffe750 | ||
![]() |
f65aeadf97 | ||
![]() |
03f463ffc8 | ||
![]() |
728e5aa63e | ||
![]() |
2a7406da4f | ||
![]() |
f743eedacb | ||
![]() |
65461c17ed | ||
![]() |
1efbf3d3cf | ||
![]() |
14e4762bf5 | ||
![]() |
fd3eb6dbd3 | ||
![]() |
561193570f | ||
![]() |
f2288b2a14 | ||
![]() |
4281108d01 | ||
![]() |
1cc6f0b7ca | ||
![]() |
f6788d2b8e | ||
![]() |
8acd7991df | ||
![]() |
321da097ae | ||
![]() |
13e635fb2c | ||
![]() |
ae8b2ad0bd | ||
![]() |
576d7c4cb8 | ||
![]() |
b0e25793f1 | ||
![]() |
eb91801d3e | ||
![]() |
616c112b12 | ||
![]() |
1425c335af | ||
![]() |
f777971d6d | ||
![]() |
4c5e1fa83c | ||
![]() |
dcad795964 | ||
![]() |
37632245d8 | ||
![]() |
9018700e94 | ||
![]() |
11acd15e70 | ||
![]() |
7619e79b94 | ||
![]() |
c7cf5de709 | ||
![]() |
273b6abb78 | ||
![]() |
87bca14eb5 | ||
![]() |
8e05706e43 | ||
![]() |
3836013160 | ||
![]() |
fd98f44d05 | ||
![]() |
0396471168 | ||
![]() |
b7db679f4b | ||
![]() |
0cbadbacfa | ||
![]() |
1ce7be88a0 | ||
![]() |
53dda7f0e4 | ||
![]() |
026e812e04 | ||
![]() |
986730477b | ||
![]() |
9984ee0402 | ||
![]() |
dae9d88636 | ||
![]() |
7879d79201 | ||
![]() |
ed1da6607e | ||
![]() |
c70fbba1bd | ||
![]() |
ffe8047e9a | ||
![]() |
d8f67aa451 | ||
![]() |
c604486551 | ||
![]() |
80c1fcca98 | ||
![]() |
dc73f4f963 | ||
![]() |
da4725492d | ||
![]() |
7668c4b549 | ||
![]() |
b769c20e3f | ||
![]() |
44240d2ab3 | ||
![]() |
da1f8da3d4 | ||
![]() |
1cf278b531 | ||
![]() |
09b55c2859 | ||
![]() |
c81901f651 | ||
![]() |
a2273a4c3b | ||
![]() |
3cd24426bf | ||
![]() |
f3809e03c1 |
8
.eslintignore
Normal file
8
.eslintignore
Normal file
@@ -0,0 +1,8 @@
|
||||
es/**/*
|
||||
lib/**/*
|
||||
node_modules
|
||||
_site
|
||||
dist
|
||||
coverage
|
||||
**/*.d.ts
|
||||
.eslintrc.js
|
9
.eslintrc.js
Normal file
9
.eslintrc.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
extends: [require.resolve("@umijs/fabric/dist/eslint")],
|
||||
plugins: ["simple-import-sort"],
|
||||
rules: {
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
"@typescript-eslint/no-parameter-properties": 0,
|
||||
},
|
||||
};
|
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -8,8 +8,8 @@ assignees:
|
||||
|
||||
### 🐛 Bug 描述 Bug description
|
||||
|
||||
<!-- 请在上方详细地描述 bug,让大家都能理解。 -->
|
||||
<!-- Please describe the bug in detail above so that everyone can understand. -->
|
||||
<!-- 请在上方详细地描述 bug,让大家都能理解。建议附上使用代码。 -->
|
||||
<!-- Please describe the bug in detail above so that everyone can understand. It is recommended to attach the use code. -->
|
||||
|
||||
### 🏞 期望结果 Desired result
|
||||
|
||||
|
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -8,11 +8,11 @@ First of all, thank you for your contribution! 😄
|
||||
- [ ] 新特性提交 / New feature
|
||||
- [ ] bug 修复 / Fix bug
|
||||
- [ ] 样式优化 / Style optimization
|
||||
- [ ] 包体积优化 / Package size optimization
|
||||
- [ ] 性能优化 / Performance optimization
|
||||
- [ ] 代码风格优化 / Code style optimization
|
||||
- [ ] 性能优化 / Performance optimization
|
||||
- [ ] 构建优化 / Build optimization
|
||||
- [ ] 网站、文档、Demo 改进 / Website, documentation, demo improvements
|
||||
- [ ] 重构代码或样式 / Refactor code or style
|
||||
- [ ] 测试相关 / Test related
|
||||
- [ ] 其他 / Other
|
||||
|
||||
@@ -42,14 +42,4 @@ Describe changes from the user side, and list all potential break changes or oth
|
||||
| 🇺🇸 English | |
|
||||
| 🇨🇳 Chinese | |
|
||||
|
||||
|
||||
### ☑️ 请求合并前的自查清单 / Self Check before Merge
|
||||
|
||||
⚠️ 请自检并全部**勾选全部选项**。/ Please check all items below before review. ⚠️
|
||||
|
||||
- [ ] 文档已补充或无须补充 / Doc is updated/provided or not needed
|
||||
- [ ] 代码演示已提供或无须提供 / Demo is updated/provided or not needed
|
||||
- [ ] TypeScript 定义已补充或无须补充 / TypeScript definition is updated/provided or not needed
|
||||
- [ ] Changelog 已提供或无须提供 / Changelog is provided or not needed
|
||||
|
||||
<!-- From: https://github.com/one-template/pr-template -->
|
||||
|
25
.github/workflows/ci-notice.yml
vendored
Normal file
25
.github/workflows/ci-notice.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: CI Notice
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@main
|
||||
|
||||
- uses: actions-cool/ci-notice@main
|
||||
with:
|
||||
ci: |
|
||||
yarn
|
||||
yarn run package
|
||||
yarn run docs:build
|
||||
notice-types: 'issue'
|
||||
issue-assignees: 'xrkffgg'
|
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -5,6 +5,9 @@ on: [push, pull_request]
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@main
|
||||
@@ -12,8 +15,11 @@ jobs:
|
||||
- name: install
|
||||
run: yarn install
|
||||
|
||||
- name: package
|
||||
run: yarn package
|
||||
- name: format
|
||||
run: yarn format-check
|
||||
|
||||
- name: test
|
||||
run: yarn test
|
||||
|
||||
- name: package
|
||||
run: yarn docs:build
|
||||
run: yarn package
|
||||
|
22
.github/workflows/gh-pages.yml
vendored
Normal file
22
.github/workflows/gh-pages.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: npm run docs:build
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs-dist
|
40
.github/workflows/preview-build.yml
vendored
Normal file
40
.github/workflows/preview-build.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: Preview Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
build-preview:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
yarn
|
||||
yarn docs:preview
|
||||
|
||||
- run: |
|
||||
zip -r dist.zip docs-dist
|
||||
|
||||
- name: upload dist artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist.zip
|
||||
retention-days: 5
|
||||
|
||||
- name: Save PR number
|
||||
if: ${{ always() }}
|
||||
run: echo ${{ github.event.number }} > ./pr-id.txt
|
||||
|
||||
- name: Upload PR number
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: pr
|
||||
path: ./pr-id.txt
|
92
.github/workflows/preview-deploy.yml
vendored
Normal file
92
.github/workflows/preview-deploy.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
name: Preview Deploy
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Preview Build"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
success:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: download pr artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
name: pr
|
||||
|
||||
- name: save PR id
|
||||
id: pr
|
||||
run: echo "::set-output name=id::$(<pr-id.txt)"
|
||||
|
||||
- name: download dist artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
workflow_conclusion: success
|
||||
name: dist
|
||||
|
||||
- run: |
|
||||
unzip dist.zip
|
||||
|
||||
- name: upload surge service
|
||||
id: deploy
|
||||
run: |
|
||||
export DEPLOY_DOMAIN=https://issues-helper-preview-pr-${{ steps.pr.outputs.id }}.surge.sh
|
||||
npx surge --project ./docs-dist --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }}
|
||||
|
||||
- name: update status comment
|
||||
uses: actions-cool/maintain-one-comment@v1.1.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
🎊 PR Preview has been successfully built and deployed to https://issues-helper-preview-pr-${{ steps.pr.outputs.id }}.surge.sh
|
||||
|
||||
<img width="300" src="https://user-images.githubusercontent.com/507615/90250366-88233900-de6e-11ea-95a5-84f0762ffd39.png">
|
||||
|
||||
<!-- Sticky Pull Request Comment -->
|
||||
body-include: '<!-- Sticky Pull Request Comment -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
- name: The job failed
|
||||
if: ${{ failure() }}
|
||||
uses: actions-cool/maintain-one-comment@v1.1.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
😭 Deploy PR Preview failed.
|
||||
|
||||
<img width="300" src="https://user-images.githubusercontent.com/507615/90250824-4e066700-de6f-11ea-8230-600ecc3d6a6b.png">
|
||||
|
||||
<!-- Sticky Pull Request Comment -->
|
||||
body-include: '<!-- Sticky Pull Request Comment -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
||||
|
||||
failed:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'failure'
|
||||
steps:
|
||||
- name: download pr artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
name: pr
|
||||
|
||||
- name: save PR id
|
||||
id: pr
|
||||
run: echo "::set-output name=id::$(<pr-id.txt)"
|
||||
|
||||
- name: The job failed
|
||||
uses: actions-cool/maintain-one-comment@v1.1.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
😭 Deploy PR Preview failed.
|
||||
|
||||
<img width="300" src="https://user-images.githubusercontent.com/507615/90250824-4e066700-de6f-11ea-8230-600ecc3d6a6b.png">
|
||||
|
||||
<!-- Sticky Pull Request Comment -->
|
||||
body-include: '<!-- Sticky Pull Request Comment -->'
|
||||
number: ${{ steps.pr.outputs.id }}
|
19
.github/workflows/preview-start.yml
vendored
Normal file
19
.github/workflows/preview-start.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Preview Start
|
||||
|
||||
on: pull_request_target
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: create
|
||||
uses: actions-cool/maintain-one-comment@v1.1.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
⚡️ Deploying PR Preview...
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/507615/90240294-8d2abd00-de5b-11ea-8140-4840a0b2d571.gif" width="300" />
|
||||
|
||||
<!-- Sticky Pull Request Comment -->
|
||||
body-include: '<!-- Sticky Pull Request Comment -->'
|
20
.github/workflows/surge-preview.yml
vendored
20
.github/workflows/surge-preview.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: 🔂 Surge PR Preview
|
||||
|
||||
on: pull_request_target
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
- uses: afc163/surge-preview@v1
|
||||
with:
|
||||
surge_token: ${{ secrets.SURGE_TOKEN }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
build: |
|
||||
yarn
|
||||
yarn docs-dev:build
|
||||
dist: docs-dist
|
||||
teardown: 'true'
|
7
.gitignore
vendored
7
.gitignore
vendored
@@ -18,7 +18,7 @@ yarn-error.log*
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
yarn.lock
|
||||
# yarn.lock
|
||||
package-lock.json
|
||||
|
||||
# local env files
|
||||
@@ -47,6 +47,11 @@ package-lock.json
|
||||
.umi-test
|
||||
.env.local
|
||||
|
||||
# dumi
|
||||
web/.dumi/tmp
|
||||
web/.dumi/tmp-test
|
||||
web/.dumi/tmp-production
|
||||
|
||||
# cache
|
||||
.sass-cache/
|
||||
|
||||
|
6
.prettierignore
Normal file
6
.prettierignore
Normal file
@@ -0,0 +1,6 @@
|
||||
dist/
|
||||
lib/
|
||||
docs-dist/
|
||||
node_modules/
|
||||
src/.umi/
|
||||
src/main.ts
|
8
.prettierrc.js
Normal file
8
.prettierrc.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const fabric = require('@umijs/fabric');
|
||||
|
||||
module.exports = {
|
||||
...fabric.prettier,
|
||||
arrowParens: 'avoid',
|
||||
importOrder: ['^@formily/(.*)', '^@(.*)$', '^[./]'],
|
||||
importOrderSeparation: true,
|
||||
};
|
@@ -1,4 +0,0 @@
|
||||
export default {
|
||||
base: '/',
|
||||
publicPath: '/',
|
||||
};
|
82
.umirc.ts
82
.umirc.ts
@@ -1,82 +0,0 @@
|
||||
// more config: https://d.umijs.org/config
|
||||
import { defineConfig } from 'dumi';
|
||||
|
||||
const name = 'issues-helper';
|
||||
|
||||
export default defineConfig({
|
||||
title: 'Issue Helper',
|
||||
mode: 'site',
|
||||
favicon:
|
||||
'https://avatars1.githubusercontent.com/u/73879334?s=200&v=4',
|
||||
logo:
|
||||
'https://avatars1.githubusercontent.com/u/73879334?s=200&v=4',
|
||||
exportStatic: {},
|
||||
outputPath: 'docs-dist',
|
||||
hash: true,
|
||||
base: `/${name}/`,
|
||||
publicPath: `/${name}/`,
|
||||
locales: [
|
||||
['zh-CN', '中文'],
|
||||
['en-US', 'English'],
|
||||
],
|
||||
theme: {
|
||||
'@c-primary': '#42a5f5',
|
||||
},
|
||||
navs: {
|
||||
'zh-CN': [
|
||||
{ title: '指 南', path: '/guide' },
|
||||
{ title: '基 础', path: '/base' },
|
||||
{ title: '进 阶', path: '/advanced' },
|
||||
{ title: '更新日志', path: '/changelog' },
|
||||
{ title: 'GitHub', path: 'https://github.com/actions-cool/issues-helper' },
|
||||
],
|
||||
'en-US': [
|
||||
{ title: 'Guide', path: '/en-US/guide' },
|
||||
{ title: 'Base', path: '/en-US/base' },
|
||||
{ title: 'Advanced', path: '/en-US/advanced' },
|
||||
{ title: 'Changelog', path: '/en-US/changelog' },
|
||||
{ title: 'GitHub', path: 'https://github.com/actions-cool/issues-helper' },
|
||||
]
|
||||
},
|
||||
menus: {
|
||||
'/guide': [
|
||||
{
|
||||
title: '🍭 介 绍',
|
||||
children: ['/guide/index', '/guide/start'],
|
||||
},
|
||||
{
|
||||
title: '🎁 参 考',
|
||||
path: '/guide/ref',
|
||||
},
|
||||
{
|
||||
title: '💬 FAQ',
|
||||
path: '/guide/faq',
|
||||
},
|
||||
],
|
||||
'/en-US/guide': [
|
||||
{
|
||||
title: '🍭 Guide',
|
||||
children: ['/guide/index', '/guide/start'],
|
||||
},
|
||||
{
|
||||
title: '🎁 Reference',
|
||||
path: '/guide/ref',
|
||||
},
|
||||
{
|
||||
title: '💬 FAQ',
|
||||
path: '/guide/faq',
|
||||
},
|
||||
],
|
||||
},
|
||||
styles: [
|
||||
`
|
||||
.markdown table {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.__dumi-default-code-block + table {
|
||||
margin-top: 16px;
|
||||
}
|
||||
`,
|
||||
]
|
||||
});
|
255
CHANGELOG.md
Normal file
255
CHANGELOG.md
Normal file
@@ -0,0 +1,255 @@
|
||||
<!--
|
||||
🐞 Bug fix
|
||||
🚀 New feature
|
||||
💄 Perf
|
||||
📝 Docs
|
||||
⚡️ Code style
|
||||
🛠 refactor
|
||||
-->
|
||||
|
||||
## v3.5.0
|
||||
|
||||
- 🚀 feat: support `inactive-mode`. Optional `comment`, which will check the last comment update time. [#158](https://github.com/actions-cool/issues-helper/pull/158)
|
||||
|
||||
## v3.4.0
|
||||
|
||||
`2023.02.06`
|
||||
|
||||
- 🚀 feat: support `toggle-labels`. [#132](https://github.com/actions-cool/issues-helper/pull/132) [@Wxh16144](https://github.com/Wxh16144)
|
||||
|
||||
## v3.3.3
|
||||
|
||||
`2022.11.13`
|
||||
|
||||
- 🐞 fix: body null case. [#129](https://github.com/actions-cool/issues-helper/pull/129) [@madmansn0w](https://github.com/madmansn0w)
|
||||
|
||||
## v3.3.2
|
||||
|
||||
`2022.10.21`
|
||||
|
||||
- 💄 chore: update `@actions/core` version. [#125](https://github.com/actions-cool/issues-helper/pull/125) [@wjz304](https://github.com/wjz304)
|
||||
|
||||
## v3.3.1
|
||||
|
||||
`2022.10.19`
|
||||
|
||||
- 🐞 fix: body null case. [#123](https://github.com/actions-cool/issues-helper/pull/123)
|
||||
|
||||
## v3.3.0
|
||||
|
||||
`2022.09.02`
|
||||
|
||||
- 🚀 feat: add `get-issue`. [#114](https://github.com/actions-cool/issues-helper/pull/114)
|
||||
|
||||
## v3.2.1
|
||||
|
||||
`2022.08.31`
|
||||
|
||||
- 🐞 fix: mark-duplicate labels invalid. [#116](https://github.com/actions-cool/issues-helper/pull/116)
|
||||
|
||||
## v3.2.0
|
||||
|
||||
`2022.08.26`
|
||||
|
||||
- 🚀 feat: add `$exclude-empty` for `exclude-labels`. [#112](https://github.com/actions-cool/issues-helper/pull/112)
|
||||
- When set to include `$exclude-empty`, no label issue can be excluded
|
||||
|
||||
## v3.1.0
|
||||
|
||||
`2022.08.09`
|
||||
|
||||
- 🚀 feat: add reason for closing issue. [#110](https://github.com/actions-cool/issues-helper/pull/110) [@Xhofe](https://github.com/Xhofe)
|
||||
|
||||
## v3.0.1
|
||||
|
||||
`2022.08.01`
|
||||
|
||||
- 🐞 fix: check will undefined.
|
||||
|
||||
## v3.0.0
|
||||
|
||||
`2022.02.15`
|
||||
|
||||
- 🚀 New Feature
|
||||
- `mark-assignees`: Comment quick settings assignees
|
||||
- `find-issues`: Conditional query current warehouse issues
|
||||
- 🐞 Bug Fix
|
||||
- Fixed `find-comments` return result direction not working
|
||||
- Fix `lock-issues` lock and comment order issue
|
||||
- 🛠 Refactor
|
||||
- `contents` renamed to easy-to-understand `emoji`
|
||||
- `issue-emojis` renamed to `issue-emoji`
|
||||
- deleteComment updateComment no longer supports `out-comments`, keeping pure functionality
|
||||
- Remove title body default
|
||||
- `month-statistics` is removed
|
||||
|
||||
## v2.5.0
|
||||
|
||||
`2021.10.19`
|
||||
|
||||
- 🚀 feat: add thanks.
|
||||
|
||||
> 🐣 This will be the last version of 2.x, 3.x is under development.
|
||||
|
||||
## v2.4.3
|
||||
|
||||
`2021.09.13`
|
||||
|
||||
- 🚀 feat: default number support `issue-comment`. [#90](https://github.com/actions-cool/issues-helper/pull/90)
|
||||
|
||||
## v2.4.2
|
||||
|
||||
`2021.09.06`
|
||||
|
||||
- 🐞 fix: `doRemoveLabels` when has no label. [#88](https://github.com/actions-cool/issues-helper/pull/88)
|
||||
|
||||
## v2.4.1
|
||||
|
||||
`2021.09.05`
|
||||
|
||||
- 🐞 fix: remove labels define error. [#86](https://github.com/actions-cool/issues-helper/pull/86)
|
||||
|
||||
## v2.4.0
|
||||
|
||||
`2021.08.15`
|
||||
|
||||
- 🚀 feat: support custom repo. [#83](https://github.com/actions-cool/issues-helper/pull/83)
|
||||
- 🚀 feat: support default issueNumber get from context. [#81](https://github.com/actions-cool/issues-helper/pull/81)
|
||||
- 🐞 fix: action run async. [#79](https://github.com/actions-cool/issues-helper/pull/79)
|
||||
|
||||
## v2.3.1
|
||||
|
||||
`2021.08.09`
|
||||
|
||||
- ⚡️ refactor: extract exclude-labels array to outer scope. [#75](https://github.com/actions-cool/issues-helper/pull/75) [@meteorlxy](https://github.com/meteorlxy)
|
||||
|
||||
## v2.3.0
|
||||
|
||||
`2021.08.09`
|
||||
|
||||
- 🚀 feat: add exclude-labels for `check-inactive` `close-issues` `lock-issues`. [#74](https://github.com/actions-cool/issues-helper/pull/74)
|
||||
|
||||
## v2.2.1
|
||||
|
||||
`2021.03.21`
|
||||
|
||||
- fix: list comment page lost in `find-comments`. [#66](https://github.com/actions-cool/issues-helper/pull/66)
|
||||
|
||||
## v2.2.0
|
||||
|
||||
`2021.03.21`
|
||||
|
||||
- feat: Added `title-excludes` parameter to `check-issue`. [#65](https://github.com/actions-cool/issues-helper/pull/65)
|
||||
|
||||
## v2.1.2
|
||||
|
||||
`2021.02.19`
|
||||
|
||||
- feat: update/delete comment support find-comments out. [#63](https://github.com/actions-cool/issues-helper/pull/63)
|
||||
|
||||
## v2.1.1
|
||||
|
||||
`2021.02.03`
|
||||
|
||||
- fix: api request limit. [#57](https://github.com/actions-cool/issues-helper/pull/57)
|
||||
- chore: add catch. [#59](https://github.com/actions-cool/issues-helper/pull/59)
|
||||
|
||||
## v2.1.0
|
||||
|
||||
`2021.02.02`
|
||||
|
||||
- feat: add create-label. [#54](https://github.com/actions-cool/issues-helper/pull/54)
|
||||
|
||||
## v2.0.0
|
||||
|
||||
`2021.01.26`
|
||||
|
||||
- refactor: add require-permission default. [#51](https://github.com/actions-cool/issues-helper/pull/51)
|
||||
|
||||
## v1.12
|
||||
|
||||
> It will be the last version of 1.x
|
||||
|
||||
`2021.01.26`
|
||||
|
||||
- feat: add require-permission. [#46](https://github.com/actions-cool/issues-helper/pull/46) [#48](https://github.com/actions-cool/issues-helper/pull/48)
|
||||
- feat: add lock-reason. [#49](https://github.com/actions-cool/issues-helper/pull/49)
|
||||
|
||||
## v1.11
|
||||
|
||||
`2021.01.14`
|
||||
|
||||
- feat: add question mark duplicate. [#38](https://github.com/actions-cool/issues-helper/pull/38)
|
||||
- perf: expand duplicate action. [#40](https://github.com/actions-cool/issues-helper/pull/40)
|
||||
|
||||
## v1.10
|
||||
|
||||
`2021.01.12`
|
||||
|
||||
- fix: duplicate labels set. [#36](https://github.com/actions-cool/issues-helper/pull/36)
|
||||
|
||||
## v1.9
|
||||
|
||||
`2021.01.11`
|
||||
|
||||
- feat: add random to. [#35](https://github.com/actions-cool/issues-helper/pull/35)
|
||||
|
||||
## v1.8
|
||||
|
||||
`2021.01.07`
|
||||
|
||||
- [#31](https://github.com/actions-cool/issues-helper/pull/31)
|
||||
- refactor: split content
|
||||
- feat: add `remove-labels` for duplicate
|
||||
- docs: optimize website
|
||||
|
||||
## v1.7
|
||||
|
||||
`2021.01.02`
|
||||
|
||||
- [#27](https://github.com/actions-cool/issues-helper/pull/27)
|
||||
- feat: add `month-statistics`
|
||||
- fix: query issues less because pages max 100
|
||||
- fix: js nested `require`
|
||||
|
||||
## v1.6
|
||||
|
||||
`2020.12.30`
|
||||
|
||||
- perf: optimize duplicate. [#24](https://github.com/actions-cool/issues-helper/pull/24)
|
||||
|
||||
## v1.5
|
||||
|
||||
`2020.12.30`
|
||||
|
||||
- feat: add `mark-duplicate`. [#23](https://github.com/actions-cool/issues-helper/pull/23)
|
||||
|
||||
## v1.4
|
||||
|
||||
`2020.12.29`
|
||||
|
||||
- fix: perfect `inactive-day` check. [#22](https://github.com/actions-cool/issues-helper/pull/22)
|
||||
|
||||
## v1.3
|
||||
|
||||
`2020.12.28`
|
||||
|
||||
- feat: add welcome. [#19](https://github.com/actions-cool/issues-helper/pull/19)
|
||||
|
||||
## v1.2
|
||||
|
||||
`2020.12.25`
|
||||
|
||||
- feat: add check-issue & remove labels. [#12](https://github.com/actions-cool/issues-helper/pull/12)
|
||||
|
||||
## v1.1
|
||||
|
||||
`2020.12.24`
|
||||
|
||||
- fix: yml not support array. [#11](https://github.com/actions-cool/issues-helper/pull/11)
|
||||
|
||||
## v1
|
||||
|
||||
`2020.12.23`
|
||||
|
||||
🎉 First release.
|
16
CONTRIBUTING.md
Normal file
16
CONTRIBUTING.md
Normal file
@@ -0,0 +1,16 @@
|
||||
## Dev
|
||||
|
||||
### Code
|
||||
|
||||
All code is in `/src`.
|
||||
The online code is in `/web`.
|
||||
|
||||
## release
|
||||
|
||||
direct `npm run pub`
|
||||
|
||||
### 手动
|
||||
- 删除 v2 tag
|
||||
- git push origin :refs/tags/v2
|
||||
- 把最新的 v2.1.0 推送到 远端 v2 tag
|
||||
- git push origin v2.1.0:v2
|
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 xrkffgg
|
||||
Copyright (c) 2020-present xrkffgg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
952
README.en-US.md
952
README.en-US.md
@@ -1,952 +0,0 @@
|
||||
# 🤖 Issues Helper
|
||||
|
||||
[简体中文](./README.md) | English
|
||||
|
||||
[](https://github.com/actions-cool/issues-helper/actions)
|
||||
[](https://github.com/marketplace/actions/issues-helper)
|
||||
[](https://github.com/umijs/dumi)
|
||||
[](https://github.com/actions-cool/issues-helper/releases)
|
||||
[](https://github.com/actions-cool/issues-helper/discussions)
|
||||
[](https://github.com/actions-cool/issues-helper/stargazers)
|
||||
[](https://github.com/actions-cool/issues-helper/blob/main/LICENSE)
|
||||
|
||||
A GitHub Action that easily helps you automatically manage issues
|
||||
|
||||
[Online documentation](https://actions-cool.github.io/issues-helper) | [Changelog](https://actions-cool.github.io/issues-helper/en-US/changelog)
|
||||
|
||||
## 😎 Why use GitHub Action?
|
||||
|
||||
1. Complete free
|
||||
2. Fully automatic
|
||||
3. Hosted on the GitHub server, as long as GitHub is not down, it is not affected
|
||||
|
||||
> Private projects have a limit of 2000 times per month. [Specific view](https://github.com/settings/billing). Public are unlimited.
|
||||
|
||||
## List
|
||||
|
||||
When the following list does not have the features you want, you can submit it in [What do you want?](https://github.com/actions-cool/issues-helper/discussions/18).
|
||||
|
||||
- ⭐ Base
|
||||
- [`add-assignees`](#add-assignees)
|
||||
- [`add-labels`](#add-labels)
|
||||
- [`close-issue`](#close-issue)
|
||||
- [`create-comment`](#create-comment)
|
||||
- [`create-issue`](#create-issue)
|
||||
- [`delete-comment`](#delete-comment)
|
||||
- [`lock-issue`](#lock-issue)
|
||||
- [`open-issue`](#open-issue)
|
||||
- [`remove-assignees`](#remove-assignees)
|
||||
- [`remove-labels`](#remove-labels)
|
||||
- [`set-labels`](#set-labels)
|
||||
- [`unlock-issue`](#unlock-issue)
|
||||
- [`update-comment`](#update-comment)
|
||||
- [`update-issue`](#update-issue)
|
||||
- [`welcome`](#welcome)
|
||||
- ⭐ Advanced
|
||||
- [`check-inactive`](#check-inactive)
|
||||
- [`check-issue`](#check-issue)
|
||||
- [`close-issues`](#close-issues)
|
||||
- [`find-comments`](#find-comments)
|
||||
- [`lock-issues`](#lock-issues)
|
||||
- 🌰 Example
|
||||
- [`find-comments + create-comment + update-comment`](#find-comments--create-comment--update-comment)
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
### ⭐ Base
|
||||
|
||||
In order to better display the function, the following is an example of the actual scene, please refer to it flexibly.
|
||||
|
||||
#### `add-assignees`
|
||||
|
||||
When an issue is added or modified, assign this issue to one or more people.
|
||||
|
||||
```yml
|
||||
name: Add Assigness
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
|
||||
jobs:
|
||||
add-assigness:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Add assigness
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'add-assignees'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignees: 'xxx' or 'xx1,xx2'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| assignees | Designated person. No operation when no input or empty character | string | ✖ | v1.1 |
|
||||
|
||||
- `actions` support multiple and separated by comma. Like: `add-assignees,add-labels`
|
||||
- The `name` can be modified according to the actual situation
|
||||
- [Reference to on](#github-docs)
|
||||
- `${{ github.event.issue.number }}` is the current issue. [More references](https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events)
|
||||
- `assignees` support multiple and separated by comma. Pay attention to multiple settings, you need to use the version above v1.1
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `add-labels`
|
||||
|
||||
When the content of a new issue does not contain the specified format, add labels for the issue.
|
||||
|
||||
```yml
|
||||
name: Add Labels
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
add-labels:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.issue.body, 'xxx') == false
|
||||
steps:
|
||||
- name: Add labels
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'add-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'bug' or 'xx1,xx2'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| labels | New labels. When it is not filled in or is empty character, do not add | string | ✖ | v1.1 |
|
||||
|
||||
- `labels` support multiple and separated by comma. Pay attention to multiple settings, you need to use the version above v1.1
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `close-issue`
|
||||
|
||||
Close the specified issue.
|
||||
|
||||
```yml
|
||||
- name: Close issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'close-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: xxx
|
||||
body: 'This is auto closed.'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `create-comment`
|
||||
|
||||
When a designated label is added, comment on the issue.
|
||||
|
||||
```yml
|
||||
name: Create Comment
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
create-comment:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'xxx'
|
||||
steps:
|
||||
- name: Create comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}. Add some comments.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }}。巴拉巴拉。
|
||||
contents: '+1' or '+1,heart'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| body | Add comment content | string | ✖ | v1 |
|
||||
| contents | Add [reaction](#reactions-types) | string | ✖ | v1.1 |
|
||||
|
||||
- `body` default is `Currently at ${owner}/${repo}. And this is default comment.`
|
||||
- Where `${owner}/${repo}` means the current repo
|
||||
- Return `comment-id`, which can be used for subsequent operations. [Usage reference](#outputs-use)
|
||||
- `${{ github.event.issue.user.login }}` indicates the creator of the issue
|
||||
- `contents` support multiple and separated by comma. Pay attention to multiple settings, you need to use the version above v1.1
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `create-issue`
|
||||
|
||||
Here is an example, add an issue at UTC 00:00 on the 1st of every month.
|
||||
|
||||
```yml
|
||||
name: Create Issue
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 * *"
|
||||
|
||||
jobs:
|
||||
create-issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'create-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: 'xxxx'
|
||||
body: 'xxxx'
|
||||
labels: 'xx'
|
||||
assignees: 'xxx'
|
||||
contents: '+1'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| title | The title of the new issue | string | ✖ | v1 |
|
||||
| body | The body of the new issue | string | ✖ | v1 |
|
||||
| labels | The labels for the new issue | string | ✖ | v1.1 |
|
||||
| assignees | The assignees for the new issue | string | ✖ | v1.1 |
|
||||
| contents | Add [reaction](#reactions-types) | string | ✖ | v1.1 |
|
||||
|
||||
- `title` default is `Default Title`
|
||||
- Return `issue-number`. [Usage reference](#outputs-use)
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `delete-comment`
|
||||
|
||||
According to [`comment-id`](#comment-id) delete the specified comment.
|
||||
|
||||
```yml
|
||||
- name: Delete comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'delete-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-id: xxx
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| comment-id | The comment ID | number | ✔ | v1 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `lock-issue`
|
||||
|
||||
When the `invalid` label is added, the issue is locked.
|
||||
|
||||
```yml
|
||||
name: Lock Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
lock-issue:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'invalid'
|
||||
steps:
|
||||
- name: Lock issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'lock-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `open-issue`
|
||||
|
||||
Open the specified issue.
|
||||
|
||||
```yml
|
||||
- name: Open issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'open-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: xxx
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `remove-assignees`
|
||||
|
||||
Remove the person designated by issue.
|
||||
|
||||
```yml
|
||||
- name: Remove assignees
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'remove-assignees'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignees: 'xx'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| assignees | Designated person removed. When it is an empty character, do not remove | string | ✔ | v1.1 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `remove-labels`
|
||||
|
||||
Remove the specified labels.
|
||||
|
||||
```yml
|
||||
- name: Remove labels
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'xx'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1.2 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1.2 |
|
||||
| issue-number | The number of issue | number | ✔ | v1.2 |
|
||||
| labels | The removed labels. When it is a blank character, do not remove | string | ✔ | v1.2 |
|
||||
|
||||
- `labels` supports multiple, such as `x1,x2,x3`, only the labels added by the issue will be removed
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `set-labels`
|
||||
|
||||
Replace the labels of issue.
|
||||
|
||||
```yml
|
||||
- name: Set labels
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'set-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'xx'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| labels | labels set. When empty characters, will remove all | string | ✔ | v1.1 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `unlock-issue`
|
||||
|
||||
Unlock the specified issue.
|
||||
|
||||
```yml
|
||||
- name: Unlock issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'unlock-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `update-comment`
|
||||
|
||||
Update the specified comment according to [`comment-id`](#comment-id).
|
||||
|
||||
The following example shows that 👀 is added for each new comment.
|
||||
|
||||
```yml
|
||||
name: Add eyes to each comment
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
update-comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'update-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-id: ${{ github.event.comment.id }}
|
||||
contents: 'eyes'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| comment-id | The comment ID | number | ✔ | v1 |
|
||||
| body | Update the content of comment | string | ✖ | v1 |
|
||||
| update-mode | Update mode. Default `replace`, another `append` | string | ✖ | v1 |
|
||||
| contents | Add [reaction](#reactions-types) | string | ✖ | v1.1 |
|
||||
|
||||
- When `body` is not entered, it will remain as it is
|
||||
- When `update-mode` is `append`, additional operations will be performed. Anything other than `append` will be replaced. Only effective for `body`
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `update-issue`
|
||||
|
||||
Update the specified issue according to the `issue-number`.
|
||||
|
||||
```yml
|
||||
- name: Update issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'update-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
state: 'open'
|
||||
title: 'xxx'
|
||||
body: 'xxxx'
|
||||
update-mode: 'replace'
|
||||
labels: 'xx'
|
||||
assignees: 'xxx'
|
||||
contents: '+1'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| state | Modify the status of issue, optional value `open` `closed` | string | ✖ | v1 |
|
||||
| title | Modify the title of the issue | string | ✖ | v1 |
|
||||
| body | Modify the content of issue | string | ✖ | v1 |
|
||||
| update-mode | Update mode. Default `replace`, another `append` | string | ✖ | v1 |
|
||||
| labels | Replace the labels of issue | string | ✖ | v1.1 |
|
||||
| assignees | Replace the assignees of issue | string | ✖ | v1.1 |
|
||||
| contents | Add [reaction](#reactions-types) | string | ✖ | v1.1 |
|
||||
|
||||
- `state` defaults to `open`
|
||||
- When the option is not filled, it will keep the original
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `welcome`
|
||||
|
||||
When an issue is created, the user who created the issue for the first time is welcome.
|
||||
|
||||
If the user is not creating for the first time, there is no operation.
|
||||
|
||||
```yml
|
||||
name: Issue Welcome
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
issue-welcome:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: welcome
|
||||
uses: actions-cool/issues-helper@v1.3
|
||||
with:
|
||||
actions: 'welcome'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: hi @${{ github.event.issue.user.login }}, welcome!
|
||||
labels: 'welcome1, welcome2'
|
||||
assignees: 'xx1'
|
||||
issue-contents: '+1, -1, eyes'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1.3 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1.3 |
|
||||
| body | Comment on the welcome content, no comment if you leave it blank | string | ✖ | v1.3 |
|
||||
| labels | Add labels to this issue | string | ✖ | v1.3 |
|
||||
| assignees | Add assignees to this issue | string | ✖ | v1.3 |
|
||||
| issue-contents | Add [reaction](#reactions-types) to this issue| string | ✖ | v1.3 |
|
||||
|
||||
- If these 4 options are not filled, no operation
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
### 🌟 Advanced
|
||||
|
||||
Advanced usage is not recommended to use multiple actions at the same time.
|
||||
|
||||
#### `check-inactive`
|
||||
|
||||
At UTC 0 on the 1st of each month, add the `inactive` tag to all issues that have not been active for more than 30 days.
|
||||
|
||||
```yml
|
||||
name: Check inactive
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 * *"
|
||||
|
||||
jobs:
|
||||
check-inactive:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-inactive
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'check-inactive'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
inactive-day: 30
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| body | When operating an issue, you can comment. Do not comment when not typing | string | ✖ | v1 |
|
||||
| labels | Labels filtering | string | ✖ | v1.1 |
|
||||
| issue-state | State filtering | string | ✖ | v1 |
|
||||
| issue-assignee | Assignee filtering | string | ✖ | v1 |
|
||||
| issue-creator | Creator filtering | string | ✖ | v1 |
|
||||
| issue-mentioned | Mentioned filtering | string | ✖ | v1 |
|
||||
| body-includes | Body filtering | string | ✖ | v1 |
|
||||
| title-includes | Title filtering | string | ✖ | v1 |
|
||||
| inactive-day | Inactive days filtering | number | ✖ | v1.2 |
|
||||
| inactive-label | The label name adding | string | ✖ | v1 |
|
||||
|
||||
- `labels`: When there are multiple, the query will have multiple at the same time. If not entered, all
|
||||
- `issue-state`: The default is `all`. Optional value `open` `closed`, when these 2 items are not, both are `all`
|
||||
- `issue-assignee`: Multiplayer is not supported. If you do not enter or enter *, all will be searched. Entering `none` will query issues for which the specified person is not added
|
||||
- `inactive-day`: When entering, it will filter the issue update time earlier than the current time minus the number of inactive days. If not entered, all
|
||||
- `inactive-label`: The default is `inactive`, others can be customized. When the project does not contain the label, it will be created automatically
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `check-issue`
|
||||
|
||||
Check whether the issue meets the conditions according to the passed parameters and `issue-number`, and return a boolean value.
|
||||
|
||||
The effect of the following example is: when an issue is newly opened, verify whether the current issue designator contains `x1` or `x2`.
|
||||
|
||||
If one designated person is satisfied, the verification will pass, and at the same time, verify whether the title meets the conditions.
|
||||
|
||||
[Check rules](#check-rules)
|
||||
|
||||
```yml
|
||||
name: Check Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [edited]
|
||||
|
||||
jobs:
|
||||
check-issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'check-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignee-includes: 'x1,x2'
|
||||
title-includes: 'x1,x2/y1,y2'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1.2 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1.2 |
|
||||
| issue-number | The number of issue | number | ✔ | v1.2 |
|
||||
| assignee-includes | Assignees contains check | string | ✖ | v1.2 |
|
||||
| title-includes | Title contains check | string | ✖ | v1.2 |
|
||||
| body-includes | Body contains check | string | ✖ | v1.2 |
|
||||
|
||||
- `title-includes` `body-includes` supports the format `x1,x2` or `x1,x2/y1,y2`. Only supports two levels
|
||||
- Return `check-result`
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `close-issues`
|
||||
|
||||
Every 7 days at UTC 0, close the issues that have been filled with the `need info` label and have not been active for more than 7 days.
|
||||
|
||||
```yml
|
||||
name: Check need info
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 */7 * *"
|
||||
|
||||
jobs:
|
||||
check-need-info:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: close-issues
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'close-issues'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'need info'
|
||||
inactive-day: 7
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| body | When operating an issue, you can comment. Do not comment when not typing | string | ✖ | v1 |
|
||||
| labels | Labels filtering | string | ✖ | v1.1 |
|
||||
| issue-assignee | Assignee filtering | string | ✖ | v1 |
|
||||
| issue-creator | Creator filtering | string | ✖ | v1 |
|
||||
| issue-mentioned | Mentioned filtering | string | ✖ | v1 |
|
||||
| body-includes | Body filtering | string | ✖ | v1 |
|
||||
| title-includes | Title filtering | string | ✖ | v1 |
|
||||
| inactive-day | Inactive days filtering | number | ✖ | v1.2 |
|
||||
|
||||
- `labels`: When there are multiple, the query will have multiple at the same time. If not entered, all
|
||||
- `issue-assignee`: Multiplayer is not supported. If you do not enter or enter *, all will be searched. Entering `none` will query issues for which the specified person is not added
|
||||
- `inactive-day`: When entering, it will filter the issue update time earlier than the current time minus the number of inactive days. If not entered, all
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `find-comments`
|
||||
|
||||
Find the current warehouse issue No. 1, the creator is k and the content contains the comment list of `this`.
|
||||
|
||||
```yml
|
||||
- name: Find comments
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'find-comments'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: 1
|
||||
comment-auth: 'k'
|
||||
body-includes: 'this'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| comment-auth | Comment creator, all will be queried if not filled | string | ✖ | v1 |
|
||||
| body-includes | Comment content includes filtering, no verification if not filled | string | ✖ | v1 |
|
||||
| direction | Return `comments` sort | string | ✖ | v1 |
|
||||
|
||||
- Return `comments` in the following format:
|
||||
|
||||
```js
|
||||
[
|
||||
{id: 1, auth: 'x', body: 'xxx', created: '', updated: ''},
|
||||
{id: 2, auth: 'x', body: 'xxx', created: '', updated: ''},
|
||||
]
|
||||
```
|
||||
|
||||
- `direction` defaults to ascending order, only when `desc` is set, descending order will be returned
|
||||
- The `created` `updated` in the returned array, determined by the environment, will be UTC +0
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
#### `lock-issues`
|
||||
|
||||
Every 3 months at UTC 0 on the 1st, lock all issues that have been filled with the `inactive` label and have not been active for more than 128 days.
|
||||
|
||||
```yml
|
||||
name: Lock inactive issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 */3 *"
|
||||
|
||||
jobs:
|
||||
lock-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: lock-issues
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'lock-issues'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'inactive'
|
||||
inactive-day: 128
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](#token) | string | ✔ | v1 |
|
||||
| body | When operating an issue, you can comment. Do not comment when not typing | string | ✖ | v1 |
|
||||
| labels | Labels filtering | string | ✖ | v1.1 |
|
||||
| issue-state | State filtering | string | ✖ | v1 |
|
||||
| issue-assignee | Assignee filtering | string | ✖ | v1 |
|
||||
| issue-creator | Creator filtering | string | ✖ | v1 |
|
||||
| issue-mentioned | Mentioned filtering | string | ✖ | v1 |
|
||||
| body-includes | Body filtering | string | ✖ | v1 |
|
||||
| title-includes | Title filtering | string | ✖ | v1 |
|
||||
| inactive-day | Inactive days filtering | number | ✖ | v1.2 |
|
||||
|
||||
- `labels`: When there are multiple, the query will have multiple at the same time. If not entered, all
|
||||
- `issue-state`: The default is `all`. Optional value `open` `closed`, when these 2 items are not, both are `all`
|
||||
- `issue-assignee`: Multiplayer is not supported. If you do not enter or enter *, all will be searched. Entering `none` will query issues for which the specified person is not added
|
||||
- `inactive-day`: When entering, it will filter the issue update time earlier than the current time minus the number of inactive days. If not entered, all
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
## 🌰 Example
|
||||
|
||||
Flexible reference.
|
||||
|
||||
### `find-comments + create-comment + update-comment`
|
||||
|
||||
Hypothetical scenario: When the issue modification of the `watch` label is added, find out whether there is a comment containing `error` created by k, if there is only one, update the comment, if not, add a new comment.
|
||||
|
||||
```yml
|
||||
name: Test
|
||||
|
||||
on:
|
||||
isssue:
|
||||
types: [edited]
|
||||
|
||||
jobs:
|
||||
do-test:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'watch'
|
||||
steps:
|
||||
- name: find comments
|
||||
uses: actions-cool/issues-helper@v1
|
||||
id: fcid
|
||||
with:
|
||||
actions: 'find-comments'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
comment-auth: k
|
||||
body-includes: 'error'
|
||||
|
||||
- name: create comment
|
||||
if: ${{ steps.fcid.outputs.comments.length == 0 }}
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: 'Some error!'
|
||||
|
||||
- name: update comment
|
||||
if: ${{ steps.fcid.outputs.comments.length == 1 }}
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'update-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-id: ${{ steps.fcid.outputs.comments[0].id }}
|
||||
body: 'Some error again!'
|
||||
update-mode: 'append'
|
||||
```
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
## 🎁 Reference
|
||||
|
||||
### token
|
||||
|
||||
Need to have the person token with push permission.
|
||||
|
||||
- [Personal token application](https://github.com/settings/tokens)
|
||||
- Need to check `Full control of private repositories`
|
||||
- Project add secrets
|
||||
- Select settings, select secrets, select `New repository secret`
|
||||
- `Name` is the same as in actions
|
||||
- `Value` fill in the token just applied by the individual
|
||||
|
||||
When the token is not filled in actions or the corresponding secrets are not added to the project, it will default to github-actions <kbd>bot</kbd>. [More](https://docs.github.com/en/free-pro-team@latest/actions/reference/authentication-in-a-workflow).
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
### `outputs` use
|
||||
|
||||
```yml
|
||||
- name: Create issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
id: createissue
|
||||
with:
|
||||
actions: 'create-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check outputs
|
||||
run: echo "Outputs issue_number is ${{ steps.createissue.outputs.issue-number }}"
|
||||
```
|
||||
|
||||
[More](https://docs.github.com/en/free-pro-team@latest/actions/creating-actions/metadata-syntax-for-github-actions#outputs).
|
||||
|
||||
### GitHub Docs
|
||||
|
||||
- [Workflow syntax for GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#on)
|
||||
- [Events that trigger workflows](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows)
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
### Check rules
|
||||
|
||||
```js
|
||||
"title-includes": 'x1,x2'
|
||||
|
||||
x1
|
||||
x2
|
||||
|
||||
"x1y3y2" true
|
||||
"y2 x1" true
|
||||
"x2" true
|
||||
"x3" false
|
||||
```
|
||||
|
||||
```js
|
||||
"title-includes": 'x1,x2/y1,y2'
|
||||
|
||||
x1 + y1
|
||||
x2 + y1
|
||||
x1 + y2
|
||||
x2 + y2
|
||||
|
||||
"x1y3y2" true
|
||||
"y2 x1" true
|
||||
"1x2y" false
|
||||
"x1" false
|
||||
```
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
### Reactions types
|
||||
|
||||
| content | emoji |
|
||||
| -- | -- |
|
||||
| `+1` | 👍 |
|
||||
| `-1` | 👎 |
|
||||
| `laugh` | 😄 |
|
||||
| `confused` | 😕 |
|
||||
| `heart` | ❤️ |
|
||||
| `hooray` | 🎉 |
|
||||
| `rocket` | 🚀 |
|
||||
| `eyes` | 👀 |
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
### `comment-id`
|
||||
|
||||
Click the `···` icon in the upper right corner of a comment, select `Copy link`, and the number at the end of the url is `comment_id`.
|
||||
|
||||
⏫ [Back to list](#List)
|
||||
|
||||
## Actions Template
|
||||
|
||||
- You can directly use this [GitHub Actions workflow template](https://github.com/actions-cool/.github) repositorie template
|
||||
|
||||
- Personal exercises and tests [Actions](https://github.com/xrkffgg/test-ci) repository
|
||||
|
||||
## 💖 Who is using?
|
||||
|
||||
You can come to the following repositories for reference. Please leave a message at [**here**](https://github.com/actions-cool/issues-helper/issues/6).
|
||||
|
||||
At the same time, if you have any questions during use, you can also ask and inquire in the issue or discussion.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/ant-design/ant-design">
|
||||
<img src="https://avatars1.githubusercontent.com/u/12101536?s=200&v=4" width="46" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/vueComponent/ant-design-vue">
|
||||
<img src="https://avatars2.githubusercontent.com/u/32120805?s=200&v=4" width="46" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/umijs/dumi">
|
||||
<img src="https://avatars2.githubusercontent.com/u/33895495?s=200&v=4" width="46" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/umijs/umi">
|
||||
<img src="https://avatars2.githubusercontent.com/u/33895495?s=200&v=4" width="46" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AttoJS/vue-request">
|
||||
<img src="https://raw.githubusercontent.com/AttoJS/art/master/vue-request-logo.png" width="46" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" wdith="160">
|
||||
<strong>ant-design</strong>
|
||||
</td>
|
||||
<td align="center" wdith="160">
|
||||
<strong>ant-design-vue</strong>
|
||||
</td>
|
||||
<td align="center" wdith="160">
|
||||
<strong>dumi</strong>
|
||||
</td>
|
||||
<td align="center" wdith="160">
|
||||
<strong>umi</strong>
|
||||
</td>
|
||||
<td align="center" wdith="160">
|
||||
<strong>vue-request</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## LICENSE
|
||||
|
||||
[MIT](https://github.com/actions-cool/issues-helper/blob/main/LICENSE)
|
1296
README.zh-CN.md
Normal file
1296
README.zh-CN.md
Normal file
File diff suppressed because it is too large
Load Diff
117
USERS.js
Normal file
117
USERS.js
Normal file
@@ -0,0 +1,117 @@
|
||||
// **************************************************************************
|
||||
// step1: add to end
|
||||
// step2: npm run users
|
||||
// step3: push 3 files & open a new PR
|
||||
|
||||
/**
|
||||
* @param {string} url github repo
|
||||
* @param {string} logo logo url
|
||||
* @param {string} width auto use rectangle logo
|
||||
*/
|
||||
|
||||
const users = [
|
||||
{
|
||||
url: 'https://github.com/ant-design/ant-design',
|
||||
logo: 'https://avatars1.githubusercontent.com/u/12101536?s=200&v=4'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/vueComponent/ant-design-vue',
|
||||
logo: 'https://avatars1.githubusercontent.com/u/32120805?s=200&v=4'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/umijs/dumi',
|
||||
logo: 'https://avatars1.githubusercontent.com/u/33895495?s=200&v=4'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/umijs/umi',
|
||||
logo: 'https://avatars1.githubusercontent.com/u/33895495?s=200&v=4'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/AttoJS/vue-request',
|
||||
logo: 'https://user-images.githubusercontent.com/29775873/129506134-55044c85-24cd-47d3-81ef-dba842214d71.png'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/mui/material-ui',
|
||||
logo: 'https://avatars.githubusercontent.com/u/33663932?s=200&v=4'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/lijinke666/react-music-player',
|
||||
logo: 'https://user-images.githubusercontent.com/29775873/129506058-b0d8c741-f73a-496c-98de-7db2fb586db7.png'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/ant-design-blazor/ant-design-blazor',
|
||||
logo: 'https://user-images.githubusercontent.com/29775873/129505619-5abddb68-8663-4c71-b7d2-049c716aab26.png'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/zoo-js/zoo',
|
||||
logo: 'https://avatars1.githubusercontent.com/u/70757173?s=200&v=4'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/react-component',
|
||||
logo: 'https://avatars3.githubusercontent.com/u/9441414?s=200&v=4'
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/prettier/prettier',
|
||||
logo: 'https://user-images.githubusercontent.com/29775873/129505900-ca248179-2435-429d-9fd3-779206bcd899.png',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/vuejs/jsx-next',
|
||||
logo: 'https://avatars.githubusercontent.com/u/6128107?s=200&v=4',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/vitejs/vite',
|
||||
logo: 'https://avatars.githubusercontent.com/u/65625612?s=200&v=4',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/jdf2e/nutui',
|
||||
logo: 'https://img14.360buyimg.com/imagetools/jfs/t1/167902/2/8762/791358/603742d7E9b4275e3/e09d8f9a8bf4c0ef.png',
|
||||
},
|
||||
{
|
||||
width: 'auto',
|
||||
url: 'https://github.com/alibaba/formily',
|
||||
logo: 'https://img.alicdn.com/imgextra/i2/O1CN01Kq3OHU1fph6LGqjIz_!!6000000004056-55-tps-1141-150.svg',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/vuepress/vuepress-next',
|
||||
logo: 'https://v2.vuepress.vuejs.org/images/hero.png',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/TuSimple/naive-ui',
|
||||
logo: 'https://camo.githubusercontent.com/b8ebecade711b9ae1fa306e7a1c9dd680fb56b0e2b9f015fec9cbad343570353/68747470733a2f2f6e6169766575692e6f73732d636e2d686f6e676b6f6e672e616c6979756e63732e636f6d2f6e616976656c6f676f2e737667',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/element-plus/element-plus',
|
||||
logo: 'https://avatars.githubusercontent.com/u/68583457',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/antvis/S2',
|
||||
logo: 'https://gw.alipayobjects.com/mdn/rms_56cbb2/afts/img/A*TI8XSK3W0EkAAAAAAAAAAAAAARQnAQ',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/twbs/bootstrap',
|
||||
logo: 'https://getbootstrap.com/docs/5.1/assets/brand/bootstrap-logo-shadow.png',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/nolimits4web/swiper',
|
||||
logo: 'https://user-images.githubusercontent.com/29775873/156721728-3b0021ea-6932-4a77-a104-2e0bad97346e.png',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/vitest-dev/vitest',
|
||||
logo: 'https://user-images.githubusercontent.com/11247099/145112184-a9ff6727-661c-439d-9ada-963124a281f7.png',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/electron/electron',
|
||||
logo: 'https://avatars.githubusercontent.com/u/13409222?s=200&v=4',
|
||||
},
|
||||
{
|
||||
url: 'https://github.com/ant-design/ant-design-mobile',
|
||||
logo: 'https://gw.alipayobjects.com/zos/bmw-prod/b874caa9-4458-412a-9ac6-a61486180a62.svg',
|
||||
},
|
||||
];
|
||||
|
||||
// **************************************************************************
|
||||
module.exports = {
|
||||
users
|
||||
};
|
||||
|
||||
// **************************************************************************
|
67
action.yml
67
action.yml
@@ -1,15 +1,21 @@
|
||||
name: 'Issues Helper'
|
||||
description: 'A GitHub Action that easily helps you automatically manage issues'
|
||||
author: 'xrkffgg'
|
||||
|
||||
# https://actions-cool.github.io/github-action-branding/
|
||||
branding:
|
||||
icon: 'message-square'
|
||||
color: 'black'
|
||||
|
||||
inputs:
|
||||
actions:
|
||||
description: 'Action name'
|
||||
token:
|
||||
description: 'Github_token'
|
||||
default: ${{ github.token }}
|
||||
repo:
|
||||
description: 'The repositorie'
|
||||
|
||||
issue-number:
|
||||
description: 'Issue-number'
|
||||
comment-id:
|
||||
@@ -20,22 +26,41 @@ inputs:
|
||||
description: 'Issue title'
|
||||
assignees:
|
||||
description: 'Issue assignees'
|
||||
random-to:
|
||||
description: 'Issue assignees random to'
|
||||
close-reason:
|
||||
description: 'Issue close reason'
|
||||
|
||||
# label
|
||||
labels:
|
||||
description: 'Issue labels'
|
||||
label-name:
|
||||
description: 'Create label name'
|
||||
label-color:
|
||||
description: 'Create label color, default #ededed'
|
||||
label-desc:
|
||||
description: 'Create label description'
|
||||
|
||||
state:
|
||||
description: 'Issue state'
|
||||
update-mode:
|
||||
description: 'Body update mode'
|
||||
contents:
|
||||
emoji:
|
||||
description: 'Issue reactions emoji'
|
||||
direction:
|
||||
description: 'Find comments direction'
|
||||
description: 'Find direction'
|
||||
|
||||
# comments
|
||||
comment-auth:
|
||||
description: 'Find comments query auth'
|
||||
assignee-includes:
|
||||
description: 'Check use'
|
||||
body-includes:
|
||||
description: 'Query use'
|
||||
|
||||
# check
|
||||
title-excludes:
|
||||
description: 'Remove some to check title whether empty.'
|
||||
title-includes:
|
||||
description: 'Query use'
|
||||
issue-creator:
|
||||
@@ -44,23 +69,55 @@ inputs:
|
||||
description: 'Query use'
|
||||
issue-mentioned:
|
||||
description: 'Query use'
|
||||
issue-contents:
|
||||
issue-emoji:
|
||||
description: 'For welcome'
|
||||
issue-state:
|
||||
description: 'Query use'
|
||||
inactive-day:
|
||||
description: 'Query use'
|
||||
inactive-mode:
|
||||
description: 'Inactive mode'
|
||||
lock-reason:
|
||||
description: 'The reason lock issue'
|
||||
inactive-label:
|
||||
description: 'Issue label set use'
|
||||
exclude-labels:
|
||||
description: 'Query issues exclude labels'
|
||||
assign-command:
|
||||
description: 'For mark-assigness'
|
||||
duplicate-command:
|
||||
description: 'For mark-duplicate'
|
||||
duplicate-labels:
|
||||
description: 'For mark-duplicate add labels'
|
||||
require-permission:
|
||||
description: 'Only the allow can do. Possible admin, write, read, and none.'
|
||||
remove-labels:
|
||||
description: 'For remove labels'
|
||||
close-issue:
|
||||
description: 'For mark-duplicate'
|
||||
|
||||
outputs:
|
||||
issue-number:
|
||||
description: 'Create Issue Number'
|
||||
description: 'Issue Number'
|
||||
issue-title:
|
||||
description: 'Issue Title'
|
||||
issue-body:
|
||||
description: 'Issue Body'
|
||||
issue-labels:
|
||||
description: 'Issue labels'
|
||||
issue-assignees:
|
||||
description: 'Issue assignees'
|
||||
issue-state:
|
||||
description: 'Issue state'
|
||||
comment-id:
|
||||
description: 'Create comment ID'
|
||||
comments:
|
||||
description: 'Find comments'
|
||||
issues:
|
||||
description: 'Find issues'
|
||||
check-result:
|
||||
description: 'Check issue'
|
||||
|
||||
runs:
|
||||
using: node12
|
||||
using: node16
|
||||
main: 'dist/index.js'
|
||||
|
13288
dist/index.js
vendored
13288
dist/index.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,214 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
# 🌟 Advanced
|
||||
|
||||
Advanced usage is not recommended to use multiple actions at the same time.
|
||||
|
||||
## `check-inactive`
|
||||
|
||||
At UTC 0 on the 1st of each month, add the `inactive` tag to all issues that have not been active for more than 30 days.
|
||||
|
||||
```yml
|
||||
name: Check inactive
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 * *"
|
||||
|
||||
jobs:
|
||||
check-inactive:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-inactive
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'check-inactive'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
inactive-day: 30
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| body | When operating an issue, you can comment. Do not comment when not typing | string | ✖ | v1 |
|
||||
| labels | Labels filtering | string | ✖ | v1.1 |
|
||||
| issue-state | State filtering | string | ✖ | v1 |
|
||||
| issue-assignee | Assignee filtering | string | ✖ | v1 |
|
||||
| issue-creator | Creator filtering | string | ✖ | v1 |
|
||||
| issue-mentioned | Mentioned filtering | string | ✖ | v1 |
|
||||
| body-includes | Body filtering | string | ✖ | v1 |
|
||||
| title-includes | Title filtering | string | ✖ | v1 |
|
||||
| inactive-day | Inactive days filtering | number | ✖ | v1.2 |
|
||||
| inactive-label | The label name adding | string | ✖ | v1 |
|
||||
|
||||
- `labels`: When there are multiple, the query will have multiple at the same time. If not entered, all
|
||||
- `issue-state`: The default is `all`. Optional value `open` `closed`, when these 2 items are not, both are `all`
|
||||
- `issue-assignee`: Multiplayer is not supported. If you do not enter or enter *, all will be searched. Entering `none` will query issues for which the specified person is not added
|
||||
- `inactive-day`: When entering, it will filter the issue update time earlier than the current time minus the number of inactive days. If not entered, all
|
||||
- `inactive-label`: The default is `inactive`, others can be customized. When the project does not contain the label, it will be created automatically
|
||||
|
||||
## `check-issue`
|
||||
|
||||
Check whether the issue meets the conditions according to the passed parameters and `issue-number`, and return a boolean value.
|
||||
|
||||
The effect of the following example is: when an issue is newly opened, verify whether the current issue designator contains `x1` or `x2`.
|
||||
|
||||
If one designated person is satisfied, the verification will pass, and at the same time, verify whether the title meets the conditions.
|
||||
|
||||
[Check rules](/en-US/guide/ref#-includes-check-rules)
|
||||
|
||||
```yml
|
||||
name: Check Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [edited]
|
||||
|
||||
jobs:
|
||||
check-issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'check-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignee-includes: 'x1,x2'
|
||||
title-includes: 'x1,x2/y1,y2'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1.2 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1.2 |
|
||||
| issue-number | The number of issue | number | ✔ | v1.2 |
|
||||
| assignee-includes | Assignees contains check | string | ✖ | v1.2 |
|
||||
| title-includes | Title contains check | string | ✖ | v1.2 |
|
||||
| body-includes | Body contains check | string | ✖ | v1.2 |
|
||||
|
||||
- `title-includes` `body-includes` supports the format `x1,x2` or `x1,x2/y1,y2`. Only supports two levels
|
||||
- Return `check-result`
|
||||
|
||||
## `close-issues`
|
||||
|
||||
Every 7 days at UTC 0, close the issues that have been filled with the `need info` label and have not been active for more than 7 days.
|
||||
|
||||
```yml
|
||||
name: Check need info
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 */7 * *"
|
||||
|
||||
jobs:
|
||||
check-need-info:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: close-issues
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'close-issues'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'need info'
|
||||
inactive-day: 7
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| body | When operating an issue, you can comment. Do not comment when not typing | string | ✖ | v1 |
|
||||
| labels | Labels filtering | string | ✖ | v1.1 |
|
||||
| issue-assignee | Assignee filtering | string | ✖ | v1 |
|
||||
| issue-creator | Creator filtering | string | ✖ | v1 |
|
||||
| issue-mentioned | Mentioned filtering | string | ✖ | v1 |
|
||||
| body-includes | Body filtering | string | ✖ | v1 |
|
||||
| title-includes | Title filtering | string | ✖ | v1 |
|
||||
| inactive-day | Inactive days filtering | number | ✖ | v1.2 |
|
||||
|
||||
- `labels`: When there are multiple, the query will have multiple at the same time. If not entered, all
|
||||
- `issue-assignee`: Multiplayer is not supported. If you do not enter or enter *, all will be searched. Entering `none` will query issues for which the specified person is not added
|
||||
- `inactive-day`: When entering, it will filter the issue update time earlier than the current time minus the number of inactive days. If not entered, all
|
||||
|
||||
## `find-comments`
|
||||
|
||||
Find the current warehouse issue No. 1, the creator is k and the content contains the comment list of `this`.
|
||||
|
||||
```yml
|
||||
- name: Find comments
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'find-comments'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: 1
|
||||
comment-auth: 'k'
|
||||
body-includes: 'this'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| comment-auth | Comment creator, all will be queried if not filled | string | ✖ | v1 |
|
||||
| body-includes | Comment content includes filtering, no verification if not filled | string | ✖ | v1 |
|
||||
| direction | Return `comments` sort | string | ✖ | v1 |
|
||||
|
||||
- Return `comments` in the following format:
|
||||
|
||||
```js
|
||||
[
|
||||
{id: 1, auth: 'x', body: 'xxx', created: '', updated: ''},
|
||||
{id: 2, auth: 'x', body: 'xxx', created: '', updated: ''},
|
||||
]
|
||||
```
|
||||
|
||||
- `direction` defaults to ascending order, only when `desc` is set, descending order will be returned
|
||||
- The `created` `updated` in the returned array, determined by the environment, will be UTC +0
|
||||
|
||||
## `lock-issues`
|
||||
|
||||
Every 3 months at UTC 0 on the 1st, lock all issues that have been filled with the `inactive` label and have not been active for more than 128 days.
|
||||
|
||||
```yml
|
||||
name: Lock inactive issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 */3 *"
|
||||
|
||||
jobs:
|
||||
lock-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: lock-issues
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'lock-issues'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'inactive'
|
||||
inactive-day: 128
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| body | When operating an issue, you can comment. Do not comment when not typing | string | ✖ | v1 |
|
||||
| labels | Labels filtering | string | ✖ | v1.1 |
|
||||
| issue-state | State filtering | string | ✖ | v1 |
|
||||
| issue-assignee | Assignee filtering | string | ✖ | v1 |
|
||||
| issue-creator | Creator filtering | string | ✖ | v1 |
|
||||
| issue-mentioned | Mentioned filtering | string | ✖ | v1 |
|
||||
| body-includes | Body filtering | string | ✖ | v1 |
|
||||
| title-includes | Title filtering | string | ✖ | v1 |
|
||||
| inactive-day | Inactive days filtering | number | ✖ | v1.2 |
|
||||
|
||||
- `labels`: When there are multiple, the query will have multiple at the same time. If not entered, all
|
||||
- `issue-state`: The default is `all`. Optional value `open` `closed`, when these 2 items are not, both are `all`
|
||||
- `issue-assignee`: Multiplayer is not supported. If you do not enter or enter *, all will be searched. Entering `none` will query issues for which the specified person is not added
|
||||
- `inactive-day`: When entering, it will filter the issue update time earlier than the current time minus the number of inactive days. If not entered, all
|
210
docs/advanced.md
210
docs/advanced.md
@@ -1,210 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
# 🌟 进 阶
|
||||
|
||||
进阶用法不建议 actions 多个一次同时使用。
|
||||
|
||||
## `check-inactive`
|
||||
|
||||
每月 1 号 UTC 0 时,对所有 30 天以上未活跃的 issues 增加 `inactive` 标签。
|
||||
|
||||
```yml
|
||||
name: Check inactive
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 * *"
|
||||
|
||||
jobs:
|
||||
check-inactive:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-inactive
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'check-inactive'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
inactive-day: 30
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| body | 操作 issue 时,可进行评论。不填时,不评论 | string | ✖ | v1 |
|
||||
| labels | 标签筛选 | string | ✖ | v1.1 |
|
||||
| issue-state | 状态筛选 | string | ✖ | v1 |
|
||||
| issue-assignee | 指定人筛选 | string | ✖ | v1 |
|
||||
| issue-creator | 创建人筛选 | string | ✖ | v1 |
|
||||
| issue-mentioned | 提及人筛选 | string | ✖ | v1 |
|
||||
| body-includes | 包含内容筛选 | string | ✖ | v1 |
|
||||
| title-includes | 包含标题筛选 | string | ✖ | v1 |
|
||||
| inactive-day | 非活跃天数筛选 | number | ✖ | v1.2 |
|
||||
| inactive-label | 新增标签名称 | string | ✖ | v1 |
|
||||
|
||||
- `labels`:为多个时,会查询同时拥有多个。不填时,会查询所有
|
||||
- `issue-state`:默认为 `all`。可选值 `open` `closed`,非这 2 项时,均为 `all`
|
||||
- `issue-assignee`:不支持多人。不填或输入 * 时,查询所有。输入 `none` 会查询未添加指定人的 issues
|
||||
- `inactive-day`:当输入时,会筛选 issue 更新时间早于当前时间减去非活跃天数。不填时,会查询所有
|
||||
- `inactive-label`:默认为 `inactive`,可自定义其他。当项目未包含该 label 时,会自动新建
|
||||
|
||||
## `check-issue`
|
||||
|
||||
根据传入的参数和 `issue-number` 来检查该 issue 是否满足条件,返回一个布尔值。
|
||||
|
||||
下面的例子效果是:当 issue 新开时,校验当前 issue 指定人是否包含 `x1` 或者 `x2`,满足一个指定人即可校验通过,同时校验标题是否满足条件,[校验规则](/guide/ref#-includes-校验规则)。
|
||||
|
||||
```yml
|
||||
name: Check Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [edited]
|
||||
|
||||
jobs:
|
||||
check-issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'check-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignee-includes: 'x1,x2'
|
||||
title-includes: 'x1,x2/y1,y2'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1.2 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1.2 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1.2 |
|
||||
| assignee-includes | 是否包含指定人 | string | ✖ | v1.2 |
|
||||
| title-includes | 标题包含校验 | string | ✖ | v1.2 |
|
||||
| body-includes | 内容包含校验 | string | ✖ | v1.2 |
|
||||
|
||||
- `title-includes` `body-includes` 支持格式 `x1,x2` 或者 `x1,x2/y1,y2`。只支持两个层级
|
||||
- 返回 `check-result`
|
||||
|
||||
## `close-issues`
|
||||
|
||||
每 7 天 UTC 0 时,关闭已填加 `need info` label 且 7 天以上未活跃的 issues。
|
||||
|
||||
```yml
|
||||
name: Check need info
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 */7 * *"
|
||||
|
||||
jobs:
|
||||
check-need-info:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: close-issues
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'close-issues'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'need info'
|
||||
inactive-day: 7
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| body | 操作 issue 时,可进行评论。不填时,不评论 | string | ✖ | v1 |
|
||||
| labels | 标签筛选 | string | ✖ | v1.1 |
|
||||
| issue-assignee | 指定人筛选 | string | ✖ | v1 |
|
||||
| issue-creator | 创建人筛选 | string | ✖ | v1 |
|
||||
| issue-mentioned | 提及人筛选 | string | ✖ | v1 |
|
||||
| body-includes | 包含内容筛选 | string | ✖ | v1 |
|
||||
| title-includes | 包含标题筛选 | string | ✖ | v1 |
|
||||
| inactive-day | 非活跃天数筛选 | number | ✖ | v1.2 |
|
||||
|
||||
- `labels`:为多个时,会查询同时拥有多个。不填时,会查询所有
|
||||
- `issue-assignee`:不支持多人。不填或输入 * 时,查询所有。输入 `none` 会查询未添加指定人的 issues
|
||||
- `inactive-day`:当输入时,会筛选 issue 更新时间早于当前时间减去非活跃天数。不填时,会查询所有
|
||||
|
||||
## `find-comments`
|
||||
|
||||
查找当前仓库 1 号 issue 中,创建者是 k ,内容包含 `this` 的评论列表。
|
||||
|
||||
```yml
|
||||
- name: Find comments
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'find-comments'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: 1
|
||||
comment-auth: 'k'
|
||||
body-includes: 'this'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
| comment-auth | 评论创建者,不填时会查询所有 | string | ✖ | v1 |
|
||||
| body-includes | 评论内容包含过滤,不填时无校验 | string | ✖ | v1 |
|
||||
| direction | 返回 `comments` 排序 | string | ✖ | v1 |
|
||||
|
||||
- 返回 `comments`,格式如下:
|
||||
|
||||
```js
|
||||
[
|
||||
{id: 1, auth: 'x', body: 'xxx', created: '', updated: ''},
|
||||
{id: 2, auth: 'x', body: 'xxx', created: '', updated: ''},
|
||||
]
|
||||
```
|
||||
|
||||
- `direction` 默认为升序,只有设置 `desc` 时,会返回降序
|
||||
- 返回数组中 `created` `updated`,由所处环境决定,会是 UTC +0
|
||||
|
||||
## `lock-issues`
|
||||
|
||||
每 3 个月 1 号 UTC 0 时,锁定已填加 `inactive` label 且 128 天以上未活跃的所有 issues。
|
||||
|
||||
```yml
|
||||
name: Lock inactive issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 */3 *"
|
||||
|
||||
jobs:
|
||||
lock-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: lock-issues
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'lock-issues'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'inactive'
|
||||
inactive-day: 128
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| body | 操作 issue 时,可进行评论。不填时,不评论 | string | ✖ | v1 |
|
||||
| labels | 标签筛选 | string | ✖ | v1.1 |
|
||||
| issue-state | 状态筛选 | string | ✖ | v1 |
|
||||
| issue-assignee | 指定人筛选 | string | ✖ | v1 |
|
||||
| issue-creator | 创建人筛选 | string | ✖ | v1 |
|
||||
| issue-mentioned | 提及人筛选 | string | ✖ | v1 |
|
||||
| body-includes | 包含内容筛选 | string | ✖ | v1 |
|
||||
| title-includes | 包含标题筛选 | string | ✖ | v1 |
|
||||
| inactive-day | 非活跃天数筛选 | number | ✖ | v1.2 |
|
||||
|
||||
- `labels`:为多个时,会查询同时拥有多个。不填时,会查询所有
|
||||
- `issue-state`:默认为 `all`。可选值 `open` `closed`,非这 2 项时,均为 `all`
|
||||
- `issue-assignee`:不支持多人。不填或输入 * 时,查询所有。输入 `none` 会查询未添加指定人的 issues
|
||||
- `inactive-day`:当输入时,会筛选 issue 更新时间早于当前时间减去非活跃天数。不填时,会查询所有
|
@@ -1,446 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
# ⭐ Base
|
||||
|
||||
In order to better display the function, the following is an example of the actual scene, please refer to it flexibly.
|
||||
|
||||
## `add-assignees`
|
||||
|
||||
When an issue is added or modified, assign this issue to one or more people.
|
||||
|
||||
```yml
|
||||
name: Add Assigness
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
|
||||
jobs:
|
||||
add-assigness:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Add assigness
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'add-assignees'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignees: 'xxx' or 'xx1,xx2'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| assignees | Designated person. No operation when no input or empty character | string | ✖ | v1.1 |
|
||||
|
||||
- `actions` support multiple and separated by comma. Like: `add-assignees,add-labels`
|
||||
- The `name` can be modified according to the actual situation
|
||||
- [Reference to on](/en-US/guide/ref#-github-docs)
|
||||
- `${{ github.event.issue.number }}` is the current issue. [More references](https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events)
|
||||
- `assignees` support multiple and separated by comma. Pay attention to multiple settings, you need to use the version above v1.1
|
||||
|
||||
## `add-labels`
|
||||
|
||||
When the content of a new issue does not contain the specified format, add labels for the issue.
|
||||
|
||||
```yml
|
||||
name: Add Labels
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
add-labels:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.issue.body, 'xxx') == false
|
||||
steps:
|
||||
- name: Add labels
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'add-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'bug' or 'xx1,xx2'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| labels | New labels. When it is not filled in or is empty character, do not add | string | ✖ | v1.1 |
|
||||
|
||||
- `labels` support multiple and separated by comma. Pay attention to multiple settings, you need to use the version above v1.1
|
||||
|
||||
## `close-issue`
|
||||
|
||||
Close the specified issue.
|
||||
|
||||
```yml
|
||||
- name: Close issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'close-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: xxx
|
||||
body: 'This is auto closed.'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
## `create-comment`
|
||||
|
||||
When a designated label is added, comment on the issue.
|
||||
|
||||
```yml
|
||||
name: Create Comment
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
create-comment:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'xxx'
|
||||
steps:
|
||||
- name: Create comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello @${{ github.event.issue.user.login }}. Add some comments.
|
||||
|
||||
你好 @${{ github.event.issue.user.login }}。巴拉巴拉。
|
||||
contents: '+1' or '+1,heart'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| body | Add comment content | string | ✖ | v1 |
|
||||
| contents | Add [reaction](/en-US/guide/ref#-reactions-type) | string | ✖ | v1.1 |
|
||||
|
||||
- `body` default is `Currently at ${owner}/${repo}. And this is default comment.`
|
||||
- Where `${owner}/${repo}` means the current repo
|
||||
- Return `comment-id`, which can be used for subsequent operations. [Usage reference](/en-US/guide/ref#-outputs-use)
|
||||
- `${{ github.event.issue.user.login }}` indicates the creator of the issue
|
||||
- `contents` support multiple and separated by comma. Pay attention to multiple settings, you need to use the version above v1.1
|
||||
|
||||
## `create-issue`
|
||||
|
||||
Here is an example, add an issue at UTC 00:00 on the 1st of every month.
|
||||
|
||||
```yml
|
||||
name: Create Issue
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 * *"
|
||||
|
||||
jobs:
|
||||
create-issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'create-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: 'xxxx'
|
||||
body: 'xxxx'
|
||||
labels: 'xx'
|
||||
assignees: 'xxx'
|
||||
contents: '+1'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| title | The title of the new issue | string | ✖ | v1 |
|
||||
| body | The body of the new issue | string | ✖ | v1 |
|
||||
| labels | The labels for the new issue | string | ✖ | v1.1 |
|
||||
| assignees | The assignees for the new issue | string | ✖ | v1.1 |
|
||||
| contents | Add [reaction](/en-US/guide/ref#-reactions-type) | string | ✖ | v1.1 |
|
||||
|
||||
- `title` default is `Default Title`
|
||||
- Return `issue-number`. [Usage reference](/en-US/guide/ref#-outputs-use)
|
||||
|
||||
## `delete-comment`
|
||||
|
||||
According to [`comment-id`](/en-US/guide/ref#-comment-id) delete the specified comment.
|
||||
|
||||
```yml
|
||||
- name: Delete comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'delete-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-id: xxx
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| comment-id | The comment ID | number | ✔ | v1 |
|
||||
|
||||
## `lock-issue`
|
||||
|
||||
When the `invalid` label is added, the issue is locked.
|
||||
|
||||
```yml
|
||||
name: Lock Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
lock-issue:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'invalid'
|
||||
steps:
|
||||
- name: Lock issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'lock-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
## `open-issue`
|
||||
|
||||
Open the specified issue.
|
||||
|
||||
```yml
|
||||
- name: Open issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'open-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: xxx
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
## `remove-assignees`
|
||||
|
||||
Remove the person designated by issue.
|
||||
|
||||
```yml
|
||||
- name: Remove assignees
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'remove-assignees'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignees: 'xx'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| assignees | Designated person removed. When it is an empty character, do not remove | string | ✔ | v1.1 |
|
||||
|
||||
## `remove-labels`
|
||||
|
||||
Remove the specified labels.
|
||||
|
||||
```yml
|
||||
- name: Remove labels
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'xx'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1.2 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1.2 |
|
||||
| issue-number | The number of issue | number | ✔ | v1.2 |
|
||||
| labels | The removed labels. When it is a blank character, do not remove | string | ✔ | v1.2 |
|
||||
|
||||
- `labels` supports multiple, such as `x1,x2,x3`, only the labels added by the issue will be removed
|
||||
|
||||
## `set-labels`
|
||||
|
||||
Replace the labels of issue.
|
||||
|
||||
```yml
|
||||
- name: Set labels
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'set-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'xx'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| labels | labels set. When empty characters, will remove all | string | ✔ | v1.1 |
|
||||
|
||||
## `unlock-issue`
|
||||
|
||||
Unlock the specified issue.
|
||||
|
||||
```yml
|
||||
- name: Unlock issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'unlock-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
|
||||
## `update-comment`
|
||||
|
||||
Update the specified comment according to [`comment-id`](/en-US/guide/ref#-comment-id).
|
||||
|
||||
The following example shows that 👀 is added for each new comment.
|
||||
|
||||
```yml
|
||||
name: Add eyes to each comment
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
update-comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'update-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-id: ${{ github.event.comment.id }}
|
||||
contents: 'eyes'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| comment-id | The comment ID | number | ✔ | v1 |
|
||||
| body | Update the content of comment | string | ✖ | v1 |
|
||||
| update-mode | Update mode. Default `replace`, another `append` | string | ✖ | v1 |
|
||||
| contents | Add [reaction](/en-US/guide/ref#-reactions-type) | string | ✖ | v1.1 |
|
||||
|
||||
- When `body` is not entered, it will remain as it is
|
||||
- When `update-mode` is `append`, additional operations will be performed. Anything other than `append` will be replaced. Only effective for `body`
|
||||
|
||||
## `update-issue`
|
||||
|
||||
Update the specified issue according to the `issue-number`.
|
||||
|
||||
```yml
|
||||
- name: Update issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'update-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
state: 'open'
|
||||
title: 'xxx'
|
||||
body: 'xxxx'
|
||||
update-mode: 'replace'
|
||||
labels: 'xx'
|
||||
assignees: 'xxx'
|
||||
contents: '+1'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1 |
|
||||
| issue-number | The number of issue | number | ✔ | v1 |
|
||||
| state | Modify the status of issue, optional value `open` `closed` | string | ✖ | v1 |
|
||||
| title | Modify the title of the issue | string | ✖ | v1 |
|
||||
| body | Modify the content of issue | string | ✖ | v1 |
|
||||
| update-mode | Update mode. Default `replace`, another `append` | string | ✖ | v1 |
|
||||
| labels | Replace the labels of issue | string | ✖ | v1.1 |
|
||||
| assignees | Replace the assignees of issue | string | ✖ | v1.1 |
|
||||
| contents | Add [reaction](/en-US/guide/ref#-reactions-type) | string | ✖ | v1.1 |
|
||||
|
||||
- `state` defaults to `open`
|
||||
- When the option is not filled, it will keep the original
|
||||
|
||||
## `welcome`
|
||||
|
||||
When an issue is created, the user who created the issue for the first time is welcome.
|
||||
|
||||
If the user is not creating for the first time, there is no operation.
|
||||
|
||||
```yml
|
||||
name: Issue Welcome
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
issue-welcome:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: welcome
|
||||
uses: actions-cool/issues-helper@v1.3
|
||||
with:
|
||||
actions: 'welcome'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: hi @${{ github.event.issue.user.login }}, welcome!
|
||||
labels: 'welcome1, welcome2'
|
||||
assignees: 'xx1'
|
||||
issue-contents: '+1, -1, eyes'
|
||||
```
|
||||
|
||||
| Param | Desc | Type | Required | Version |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | Action type | string | ✔ | v1.3 |
|
||||
| token | [Token explain](/en-US/guide/ref#-token) | string | ✔ | v1.3 |
|
||||
| body | Comment on the welcome content, no comment if you leave it blank | string | ✖ | v1.3 |
|
||||
| labels | Add labels to this issue | string | ✖ | v1.3 |
|
||||
| assignees | Add assignees to this issue | string | ✖ | v1.3 |
|
||||
| issue-contents | Add [reaction](/en-US/guide/ref#-reactions-type) to this issue| string | ✖ | v1.3 |
|
||||
|
||||
- If these 4 options are not filled, no operation
|
445
docs/base.md
445
docs/base.md
@@ -1,445 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
为了更好的展示功能,下面以实际场景举例,请灵活参考。
|
||||
|
||||
# ⭐ 基 础
|
||||
|
||||
## `add-assignees`
|
||||
|
||||
当一个 issue 新增或修改时,将这个 issue 指定某人或多人。
|
||||
|
||||
```yml
|
||||
name: Add Assigness
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
|
||||
jobs:
|
||||
add-assigness:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Add assigness
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'add-assignees'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignees: 'xxx' or 'xx1,xx2'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
| assignees | 指定人。当不填或者为空字符时,不操作 | string | ✖ | v1.1 |
|
||||
|
||||
- `actions` 支持多个,需用逗号隔开。如:`add-assignees,add-labels`
|
||||
- 其中的 `name` 可根据自行根据实际情况修改
|
||||
- [on 参考](/guide/ref#-github-相关文档)
|
||||
- `${{ github.event.issue.number }}` 表示当前 issue,[更多参考](https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events)
|
||||
- `assignees` 支持多个,需用逗号隔开。注意设置多个,需使用v1.1以上版本
|
||||
|
||||
## `add-labels`
|
||||
|
||||
当一个新增的 issue 内容不包含指定格式时,为这个 issue 添加 labels。
|
||||
|
||||
```yml
|
||||
name: Add Labels
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
add-labels:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.issue.body, 'xxx') == false
|
||||
steps:
|
||||
- name: Add labels
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'add-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'bug' or 'bug1,bug2'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
| labels | 新增的 labels。当不填或者为空字符时,不新增 | string | ✖ | v1.1 |
|
||||
|
||||
- `labels` 支持多个,需用逗号隔开。注意设置多个,需使用v1.1以上版本
|
||||
|
||||
## `close-issue`
|
||||
|
||||
关闭指定 issue。
|
||||
|
||||
```yml
|
||||
- name: Close issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'close-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: xxx
|
||||
body: 'This is auto closed.'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
|
||||
## `create-comment`
|
||||
|
||||
当新增一个指定 label 时,对该 issue 进行评论。
|
||||
|
||||
```yml
|
||||
name: Create Comment
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
create-comment:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'xxx'
|
||||
steps:
|
||||
- name: Create comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hello ${{ github.event.issue.user.login }}. Add some comments.
|
||||
|
||||
你好 ${{ github.event.issue.user.login }}。巴拉巴拉。
|
||||
contents: '+1' or '+1,heart'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
| body | 新增评论的内容 | string | ✖ | v1 |
|
||||
| contents | 为新增评论的增加 [reaction](/guide/ref#-reactions-类型) | string | ✖ | v1.1 |
|
||||
|
||||
- `body` 默认为:`Currently at ${owner}/${repo}. And this is default comment.`
|
||||
- 其中 `${owner}/${repo}` 表示当前仓库
|
||||
- 返回 `comment-id`,可用于之后操作。[用法参考](/guide/ref#-outputs-使用)
|
||||
- `${{ github.event.issue.user.login }}` 表示该 issue 的创建者
|
||||
- `contents` 支持多个,需用逗号隔开。注意设置多个,需使用v1.1以上版本
|
||||
|
||||
## `create-issue`
|
||||
|
||||
感觉新增 issue 使用场景不多。这里举例,每月 1 号 UTC 00:00 新增一个 issue。
|
||||
|
||||
```yml
|
||||
name: Create Issue
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 1 * *"
|
||||
|
||||
jobs:
|
||||
create-issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'create-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: 'xxxx'
|
||||
body: 'xxxx'
|
||||
labels: 'xx'
|
||||
assignees: 'xxx'
|
||||
contents: '+1'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| title | 新增 issue 的标题 | string | ✖ | v1 |
|
||||
| body | 新增 issue 的内容 | string | ✖ | v1 |
|
||||
| labels | 为新增 issue 添加 labels | string | ✖ | v1.1 |
|
||||
| assignees | 为新增 issue 添加 assignees | string | ✖ | v1.1 |
|
||||
| contents | 为新增 issue 增加 [reaction](/guide/ref#-reactions-类型) | string | ✖ | v1.1 |
|
||||
|
||||
- `title` 默认为:`Default Title`
|
||||
- 返回 `issue-number`,[用法参考](/guide/ref#-outputs-使用)
|
||||
|
||||
## `delete-comment`
|
||||
|
||||
根据 [`comment-id`](/guide/ref#-comment-id) 删除指定评论。
|
||||
|
||||
```yml
|
||||
- name: Delete comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'delete-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-id: xxx
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| comment-id | 指定的 comment | number | ✔ | v1 |
|
||||
|
||||
## `lock-issue`
|
||||
|
||||
当新增 `invalid` label 时,对该 issue 进行锁定。
|
||||
|
||||
```yml
|
||||
name: Lock Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
lock-issue:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'invalid'
|
||||
steps:
|
||||
- name: Lock issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'lock-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
|
||||
## `open-issue`
|
||||
|
||||
打开指定 issue。
|
||||
|
||||
```yml
|
||||
- name: Open issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'open-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: xxx
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
|
||||
## `remove-assignees`
|
||||
|
||||
移除 issue 指定人员。
|
||||
|
||||
```yml
|
||||
- name: Remove assignees
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'remove-assignees'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
assignees: 'xx'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
| assignees | 移除的指定人。当为空字符时,不进行移除 | string | ✔ | v1.1 |
|
||||
|
||||
## `remove-labels`
|
||||
|
||||
移除指定 labels。
|
||||
|
||||
```yml
|
||||
- name: Remove labels
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'xx'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1.2 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1.2 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1.2 |
|
||||
| labels | 移除的 labels。当为空字符时,不进行移除 | string | ✔ | v1.2 |
|
||||
|
||||
- `labels` 支持多个,如 `x1,x2,x3`,只会移除 issue 已添加的 labels
|
||||
|
||||
## `set-labels`
|
||||
|
||||
替换 issue 的 labels。
|
||||
|
||||
```yml
|
||||
- name: Set labels
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'set-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'xx'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
| labels | labels 设置。当空字符时,会移除所有 | string | ✔ | v1.1 |
|
||||
|
||||
## `unlock-issue`
|
||||
|
||||
解锁指定 issue。
|
||||
|
||||
```yml
|
||||
- name: Unlock issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'unlock-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
|
||||
## `update-comment`
|
||||
|
||||
根据 [`comment-id`](/guide/ref#-comment-id) 更新指定评论。
|
||||
|
||||
下面的例子展示的是,为每个新增的 comment 增加 👀 。
|
||||
|
||||
```yml
|
||||
name: Add eyes to each comment
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
update-comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update comment
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'update-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-id: ${{ github.event.comment.id }}
|
||||
contents: 'eyes'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| comment-id | 指定的 comment | number | ✔ | v1 |
|
||||
| body | 更新 comment 的内容 | string | ✖ | v1 |
|
||||
| update-mode | 更新模式。默认 `replace` 替换,`append` 附加 | string | ✖ | v1 |
|
||||
| contents | 增加 [reaction](/guide/ref#-reactions-类型) | string | ✖ | v1.1 |
|
||||
|
||||
- `body` 不填时,会保持原有
|
||||
- `update-mode` 为 `append` 时,会进行附加操作。非 `append` 都会进行替换。仅对 `body` 生效
|
||||
|
||||
## `update-issue`
|
||||
|
||||
根据 `issue-number` 更新指定 issue。
|
||||
|
||||
```yml
|
||||
- name: Update issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
with:
|
||||
actions: 'update-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
state: 'open'
|
||||
title: 'xxx'
|
||||
body: 'xxxx'
|
||||
update-mode: 'replace'
|
||||
labels: 'xx'
|
||||
assignees: 'xxx'
|
||||
contents: '+1'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1 |
|
||||
| issue-number | 指定的 issue | number | ✔ | v1 |
|
||||
| state | 修改 issue 的状态,可选值 `open` `closed` | string | ✖ | v1 |
|
||||
| title | 修改 issue 的标题 | string | ✖ | v1 |
|
||||
| body | 修改 issue 的内容 | string | ✖ | v1 |
|
||||
| update-mode | 更新模式。默认 `replace` 替换,`append` 附加 | string | ✖ | v1 |
|
||||
| labels | 替换 issue 的 labels | string | ✖ | v1.1 |
|
||||
| assignees | 替换 issue 的 assignees | string | ✖ | v1.1 |
|
||||
| contents | 增加 [reaction](/guide/ref#-reactions-类型) | string | ✖ | v1.1 |
|
||||
|
||||
- `state` 默认为 `open`
|
||||
- 当可选项不填时,会保持原有
|
||||
|
||||
|
||||
## `welcome`
|
||||
|
||||
当一个 issue 新建时,对首次新建 issue 的用户进行欢迎。若用户非首次新建,则无操作。
|
||||
|
||||
```yml
|
||||
name: Issue Welcome
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
issue-welcome:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: welcome
|
||||
uses: actions-cool/issues-helper@v1.3
|
||||
with:
|
||||
actions: 'welcome'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: hi @${{ github.event.issue.user.login }}, welcome!
|
||||
labels: 'welcome1, welcome2'
|
||||
assignees: 'xx1'
|
||||
issue-contents: '+1, -1, eyes'
|
||||
```
|
||||
|
||||
| 参数 | 描述 | 类型 | 必填 | 版本 |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| actions | 操作类型 | string | ✔ | v1.3 |
|
||||
| token | [token 说明](/guide/ref#-token-说明) | string | ✔ | v1.3 |
|
||||
| body | 评论欢迎的内容,不填则不评论 | string | ✖ | v1.3 |
|
||||
| labels | 为该 issue 增加 labels | string | ✖ | v1.3 |
|
||||
| assignees | 为该 issue 增加 assignees | string | ✖ | v1.3 |
|
||||
| issue-contents | 为该 issue 增加 [reaction](/guide/ref#-reactions-类型) | string | ✖ | v1.3 |
|
||||
|
||||
- 若这 4 个可选项都不填,则无操作
|
@@ -1,24 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
# ✨ Changelog
|
||||
|
||||
- Version rules
|
||||
- Use two-level semantic version, such as v1, v1.1, v2, v2.1
|
||||
- v1 represents the initial version
|
||||
- The fixes and additions to the v1 version will be released to the v1.1 version
|
||||
- When the released v1.x runs stable for a certain period of time, release the advanced v2 version
|
||||
- It is recommended to use the largest version and above for the parameters in the API
|
||||
|
||||
- Version selection
|
||||
- It is recommended to use the latest releases version. It can be seen in [releases](https://github.com/actions-cool/issues-helper/releases)
|
||||
- You can also refer to the update log below to select the version
|
||||
- It also supports the direct use of branch versions. Such as:
|
||||
|
||||
```yml
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@main
|
||||
```
|
||||
|
||||
<embed src="./log.md"></embed>
|
@@ -1,24 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
# ✨ 更新日志
|
||||
|
||||
- 版本规则
|
||||
- 采用两级语义化版本,如v1、v1.1、v2、v2.1
|
||||
- v1 表示初始版本
|
||||
- 对 v1 版本的修复和新增会发布到 v1.1 版本
|
||||
- 当发布的 v1.x 运行一定时间稳定后,发布进阶 v2 版本
|
||||
- API 中参数建议使用其中最大及以上版本
|
||||
|
||||
- 版本选择
|
||||
- 建议采用最新 releases 版本。可在 [releases](https://github.com/actions-cool/issues-helper/releases) 看到
|
||||
- 同时也可参照下面的更新日志来选择版本
|
||||
- 也支持直接使用分支版本。如:
|
||||
|
||||
```yml
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@main
|
||||
```
|
||||
|
||||
<embed src="./log.md"></embed>
|
@@ -1,27 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
## Is there a charge for this feature?
|
||||
|
||||
GitHub Actions is provided free of charge by GitHub. Among them, the `Private` project has a monthly limit of 2000 times, [see details](https://github.com/settings/billing). The `Public` project is unlimited.
|
||||
|
||||
## Are there any ready-made templates for reference?
|
||||
|
||||
Yes.
|
||||
|
||||
1. You can use this [GitHub Actions workflow template](https://github.com/actions-cool/.github) repository template
|
||||
2. Personal exercises and tests [Actions](https://github.com/xrkffgg/test-ci) repository
|
||||
3. You can also refer to the warehouse of [online users](/en-US#-who-is-using)
|
||||
|
||||
## I want to pause Actions, is there an easy way?
|
||||
|
||||
Yes, you can directly modify `actions`. For example: `actions:'create-comment'` is changed to `actions:'#create-comment'`. It is also convenient for recovery.
|
||||
|
||||
## So many versions, how to choose?
|
||||
|
||||
You can view the detailed [changelog](/en-US/changelog). The latest releases version is recommended.
|
||||
|
||||
## What should I do if there is no function I want here?
|
||||
|
||||
You can submit it in [What do you want?](https://github.com/actions-cool/issues-helper/discussions/18).
|
@@ -1,27 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
## 该功能是否收费?
|
||||
|
||||
GitHub Actions 是由 GitHub 免费提供的。其中 `Private` 项目每月有 2000 次的限制,[具体查看](https://github.com/settings/billing)。`Public` 项目无限制。
|
||||
|
||||
## 有没有现成的模板可以参考?
|
||||
|
||||
有的。
|
||||
|
||||
1. 你可以使用这个 [GitHub Actions workflow template](https://github.com/actions-cool/.github) 仓库的模板
|
||||
2. 个人练习和测试 [Actions](https://github.com/xrkffgg/test-ci) 的仓库
|
||||
3. 也可以来 [线上使用者](/#-谁在使用?) 的仓库参照
|
||||
|
||||
## 我想暂停 Actions,有没有简单的办法?
|
||||
|
||||
有的,你可以将直接修改 `actions`。例如:`actions: 'create-comment'` 修改为 `actions: '#create-comment'`。同时也方便恢复。
|
||||
|
||||
## 这么多版本,如何选择?
|
||||
|
||||
你可以查看详细的 [更新日志](/changelog)。推荐采用最新 releases 版本。
|
||||
|
||||
## 如果这里没有我想要的功能,该怎么办?
|
||||
|
||||
你可以在 [What do you want?](https://github.com/actions-cool/issues-helper/discussions/18) 中提出。
|
@@ -1,83 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
## 📍 `token`
|
||||
|
||||
Need to have the person token with push permission.
|
||||
|
||||
- [Personal token application](https://github.com/settings/tokens)
|
||||
- Need to check `Full control of private repositories`
|
||||
- Project add secrets
|
||||
- Select settings, select secrets, select `New repository secret`
|
||||
- `Name` is the same as in actions
|
||||
- `Value` fill in the token just applied by the individual
|
||||
|
||||
When the token is not filled in actions or the corresponding secrets are not added to the project, it will default to `github-actions-bot`. [More](https://docs.github.com/en/free-pro-team@latest/actions/reference/authentication-in-a-workflow).
|
||||
|
||||
## 📍 GitHub Docs
|
||||
|
||||
- [Workflow syntax for GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#on)
|
||||
- [Events that trigger workflows](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows)
|
||||
|
||||
## 📍 `outputs` use
|
||||
|
||||
```yml
|
||||
- name: Create issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
id: createissue
|
||||
with:
|
||||
actions: 'create-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check outputs
|
||||
run: echo "Outputs issue_number is ${{ steps.createissue.outputs.issue-number }}"
|
||||
```
|
||||
|
||||
[More](https://docs.github.com/en/free-pro-team@latest/actions/creating-actions/metadata-syntax-for-github-actions#outputs).
|
||||
|
||||
## 📍 `includes` check rules
|
||||
|
||||
```js
|
||||
"title-includes": 'x1,x2'
|
||||
|
||||
x1
|
||||
x2
|
||||
|
||||
"x1y3y2" true
|
||||
"y2 x1" true
|
||||
"x2" true
|
||||
"x3" false
|
||||
```
|
||||
|
||||
```js
|
||||
"title-includes": 'x1,x2/y1,y2'
|
||||
|
||||
x1 + y1
|
||||
x2 + y1
|
||||
x1 + y2
|
||||
x2 + y2
|
||||
|
||||
"x1y3y2" true
|
||||
"y2 x1" true
|
||||
"1x2y" false
|
||||
"x1" false
|
||||
```
|
||||
|
||||
## 📍 `Reactions` Type
|
||||
|
||||
| content | emoji |
|
||||
| -- | -- |
|
||||
| `+1` | 👍 |
|
||||
| `-1` | 👎 |
|
||||
| `laugh` | 😄 |
|
||||
| `confused` | 😕 |
|
||||
| `heart` | ❤️ |
|
||||
| `hooray` | 🎉 |
|
||||
| `rocket` | 🚀 |
|
||||
| `eyes` | 👀 |
|
||||
|
||||
For details, please [view](https://docs.github.com/en/free-pro-team@latest/rest/reference/reactions).
|
||||
|
||||
## 📍 `comment-id`
|
||||
|
||||
Click the `···` icon in the upper right corner of a comment, select `Copy link`, and the number at the end of the url is `comment_id`.
|
@@ -1,83 +0,0 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
## 📍 `token` 说明
|
||||
|
||||
需拥有 push 权限的人员 token。
|
||||
|
||||
- [个人 token 申请](https://github.com/settings/tokens)
|
||||
- 需勾选 `Full control of private repositories`
|
||||
- 项目添加 secrets
|
||||
- 选择 settings,选择 secrets,选择 `New repository secret`
|
||||
- `Name` 与 actions 中保持一致
|
||||
- `Value` 填写刚才个人申请的 token
|
||||
|
||||
当 actions 不填写 token 时,或项目未添加对应 secrets 时,会默认为 `github-actions-bot`。[更多查看](https://docs.github.com/en/free-pro-team@latest/actions/reference/authentication-in-a-workflow)。
|
||||
|
||||
## 📍 GitHub 相关文档
|
||||
|
||||
- [GitHub Actions 语法](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#on)
|
||||
- [工作流触发机制](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows)
|
||||
|
||||
## 📍 `outputs` 使用
|
||||
|
||||
```yml
|
||||
- name: Create issue
|
||||
uses: actions-cool/issues-helper@v1
|
||||
id: createissue
|
||||
with:
|
||||
actions: 'create-issue'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check outputs
|
||||
run: echo "Outputs issue_number is ${{ steps.createissue.outputs.issue-number }}"
|
||||
```
|
||||
|
||||
[更多查看](https://docs.github.com/en/free-pro-team@latest/actions/creating-actions/metadata-syntax-for-github-actions#outputs)。
|
||||
|
||||
## 📍 `includes` 校验规则
|
||||
|
||||
```js
|
||||
"title-includes": 'x1,x2'
|
||||
|
||||
x1
|
||||
x2
|
||||
|
||||
"x1y3y2" true
|
||||
"y2 x1" true
|
||||
"x2" true
|
||||
"x3" false
|
||||
```
|
||||
|
||||
```js
|
||||
"title-includes": 'x1,x2/y1,y2'
|
||||
|
||||
x1 + y1
|
||||
x2 + y1
|
||||
x1 + y2
|
||||
x2 + y2
|
||||
|
||||
"x1y3y2" true
|
||||
"y2 x1" true
|
||||
"1x2y" false
|
||||
"x1" false
|
||||
```
|
||||
|
||||
## 📍 `Reactions` 类型
|
||||
|
||||
| content | emoji |
|
||||
| -- | -- |
|
||||
| `+1` | 👍 |
|
||||
| `-1` | 👎 |
|
||||
| `laugh` | 😄 |
|
||||
| `confused` | 😕 |
|
||||
| `heart` | ❤️ |
|
||||
| `hooray` | 🎉 |
|
||||
| `rocket` | 🚀 |
|
||||
| `eyes` | 👀 |
|
||||
|
||||
如需详细了解,可 [查看](https://docs.github.com/en/free-pro-team@latest/rest/reference/reactions)。
|
||||
|
||||
## 📍 `comment-id`
|
||||
|
||||
点击某个评论右上角 `···` 图标,选择 `Copy link`,url 末尾数字即是 `comment_id`。
|
23
docs/log.md
23
docs/log.md
@@ -1,23 +0,0 @@
|
||||
## v1.3
|
||||
|
||||
`2020.12.28`
|
||||
|
||||
- feat: add welcome. [#19](https://github.com/actions-cool/issues-helper/pull/19)
|
||||
|
||||
## v1.2
|
||||
|
||||
`2020.12.25`
|
||||
|
||||
- feat: add check-issue & remove labels. [#12](https://github.com/actions-cool/issues-helper/pull/12)
|
||||
|
||||
## v1.1
|
||||
|
||||
`2020.12.24`
|
||||
|
||||
- fix: yml not support array. [#11](https://github.com/actions-cool/issues-helper/pull/11)
|
||||
|
||||
## v1
|
||||
|
||||
`2020.12.23`
|
||||
|
||||
🎉 First release.
|
@@ -1,71 +0,0 @@
|
||||
/* eslint-disable react/jsx-no-target-blank */
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const USERS = [
|
||||
{
|
||||
name: 'ant-design',
|
||||
link: 'https://github.com/ant-design/ant-design',
|
||||
logo: 'https://avatars1.githubusercontent.com/u/12101536?s=200&v=4',
|
||||
},
|
||||
{
|
||||
name: 'ant-design-vue',
|
||||
link: 'https://github.com/vueComponent/ant-design-vue',
|
||||
logo: 'https://avatars2.githubusercontent.com/u/32120805?s=200&v=4',
|
||||
},
|
||||
{
|
||||
name: 'dumi',
|
||||
link: 'https://github.com/umijs/dumi',
|
||||
logo: 'https://avatars2.githubusercontent.com/u/33895495?s=200&v=4',
|
||||
},
|
||||
{
|
||||
name: 'umi',
|
||||
link: 'https://github.com/umijs/umi',
|
||||
logo: 'https://avatars2.githubusercontent.com/u/33895495?s=200&v=4',
|
||||
},
|
||||
{
|
||||
name: 'vue-request',
|
||||
link: 'https://github.com/AttoJS/vue-request',
|
||||
logo: 'https://raw.githubusercontent.com/AttoJS/art/master/vue-request-logo.png',
|
||||
}
|
||||
];
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<ul style={{ display: 'flex', flexWrap: 'wrap', margin: 0, padding: 0, listStyle: 'none' }}>
|
||||
{USERS.map((user, i) => (
|
||||
<li
|
||||
key={user.link}
|
||||
style={{
|
||||
width: 220,
|
||||
marginRight: i === USERS.length - 1 ? 0 : 16,
|
||||
marginBottom: 8,
|
||||
border: '1px solid #eee',
|
||||
textAlign: 'center',
|
||||
fontSize: 20,
|
||||
fontWeight: 600,
|
||||
borderRadius: 2,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<a
|
||||
style={{ display: 'block', color: '#666', padding: '18px', textDecoration: 'none' }}
|
||||
target="_blank"
|
||||
href={user.link}
|
||||
>
|
||||
<img
|
||||
width={(user.name && 40) || undefined}
|
||||
height={(!user.name && 40) || undefined}
|
||||
style={{ verticalAlign: '-0.32em' }}
|
||||
src={user.logo}
|
||||
alt={user.name}
|
||||
/>
|
||||
<div style={{ marginTop: 10 }}>{user.name}</div>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
};
|
77
package.json
77
package.json
@@ -1,41 +1,64 @@
|
||||
{
|
||||
"name": "issue-helper",
|
||||
"version": "1.3.0",
|
||||
"private": true,
|
||||
"description": "Some operations on issue.",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
"start": "dumi dev",
|
||||
"docs:build": "dumi build",
|
||||
"docs-dev:build": "UMI_ENV=dev dumi build",
|
||||
"docs:deploy": "gh-pages -d docs-dist",
|
||||
"deploy": "npm run docs:build && npm run docs:deploy",
|
||||
"package": "ncc build src/main.js -o dist"
|
||||
},
|
||||
"author": "xrkffgg",
|
||||
"license": "MIT",
|
||||
"description": "A GitHub Action easily helps you automatically manage issues.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/actions-cool/issue-helper.git",
|
||||
"url": "https://github.com/actions-cool/issues-helper.git",
|
||||
"branch": "main"
|
||||
},
|
||||
"keywords": [
|
||||
"actions",
|
||||
"issue",
|
||||
"helper",
|
||||
"github"
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "xrkffgg",
|
||||
"scripts": {
|
||||
"dev": "APP_ROOT=web dumi dev",
|
||||
"start": "APP_ROOT=web dumi dev",
|
||||
"docs:build": "APP_ROOT=web dumi build",
|
||||
"docs-dev:build": "APP_ROOT=web UMI_ENV=dev dumi build",
|
||||
"docs:deploy": "gh-pages -d docs-dist",
|
||||
"docs:preview": "PREVIEW=true npm run docs:build",
|
||||
"gh-pages": "npm run docs:build && npm run docs:deploy",
|
||||
"format": "prettier --write **/*.ts **/*/*.ts",
|
||||
"format-check": "prettier --check **/*.ts **/*/*.ts",
|
||||
"lint": "eslint src/*.ts src/*/*.ts",
|
||||
"lint-fix": "eslint src/*.ts src/*/*.ts --fix",
|
||||
"lint-up": "npm run format && npm run lint-fix",
|
||||
"ci:fix": "npm run lint-up",
|
||||
"lint-all": "npm run format-check && npm run lint",
|
||||
"check-commit": "node ./scripts/check-commit.js",
|
||||
"tag": "node ./scripts/tag.js",
|
||||
"release": "node ./scripts/release",
|
||||
"test": "father test",
|
||||
"package": "ncc build src/main.ts -o dist",
|
||||
"users": "node ./scripts/update-users.js",
|
||||
"version": "node ./scripts/update-version.js",
|
||||
"pub": "sh -e ./scripts/pub.sh",
|
||||
"all": "npm run lint-all && npm run test && npm run package"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/github": "^4.0.0",
|
||||
"@octokit/rest": "^18.0.12",
|
||||
"dayjs": "^1.9.7"
|
||||
"actions-util": "^1.1.3",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash": "^4.17.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "^0.25.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"dumi": "^1.1.0-rc.8",
|
||||
"@trivago/prettier-plugin-sort-imports": "^2.0.4",
|
||||
"@types/lodash": "^4.14.175",
|
||||
"@typescript-eslint/parser": "^4.15.2",
|
||||
"@umijs/fabric": "^2.5.6",
|
||||
"@vercel/ncc": "0.34.0",
|
||||
"chalk": "^4.1.2",
|
||||
"common-tags": "^1.8.2",
|
||||
"dumi": "^2.1.21",
|
||||
"eslint": "^7.18.0",
|
||||
"eslint-plugin-github": "^4.1.1",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"father": "^2.30.7",
|
||||
"gh-pages": "^3.1.0",
|
||||
"react": "^17.0.1"
|
||||
"new-github-release-url": "^1.0.0",
|
||||
"open": "^7.3.0",
|
||||
"prettier": "^2.2.1",
|
||||
"simple-git": "^2.46.0",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
|
BIN
public/add-1.jpg
BIN
public/add-1.jpg
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
BIN
public/add-2.jpg
BIN
public/add-2.jpg
Binary file not shown.
Before Width: | Height: | Size: 48 KiB |
23
scripts/check-commit.js
Executable file
23
scripts/check-commit.js
Executable file
@@ -0,0 +1,23 @@
|
||||
const chalk = require('chalk');
|
||||
const simpleGit = require('simple-git/promise');
|
||||
|
||||
const cwd = process.cwd();
|
||||
const git = simpleGit(cwd);
|
||||
|
||||
async function checkCommit({ files }) {
|
||||
if (files.length) {
|
||||
console.log(chalk.yellow('🙄 You forgot something to commit.'));
|
||||
files.forEach(({ path: filePath }) => {
|
||||
console.log(' -', chalk.red(filePath));
|
||||
});
|
||||
console.log('');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const status = await git.status();
|
||||
await checkCommit(status);
|
||||
}
|
||||
|
||||
run();
|
14
scripts/pub.sh
Normal file
14
scripts/pub.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
echo "[TEST] check format"
|
||||
npm run format-check
|
||||
|
||||
echo "[TEST] test package"
|
||||
npm run package
|
||||
|
||||
echo "[TEST] test commit"
|
||||
npm run check-commit
|
||||
|
||||
echo "[Action] do tag"
|
||||
npm run tag
|
||||
|
||||
echo "[Action] do release"
|
||||
npm run release
|
54
scripts/release.js
Normal file
54
scripts/release.js
Normal file
@@ -0,0 +1,54 @@
|
||||
const chalk = require('chalk');
|
||||
const open = require('open');
|
||||
const newGithubReleaseUrl = require('new-github-release-url');
|
||||
const { readFileSync } = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let tag = '';
|
||||
|
||||
const CHANGELOG_NAME = 'CHANGELOG.md';
|
||||
const user = 'actions-cool';
|
||||
const repo = 'issues-helper';
|
||||
|
||||
function getChangelog(content) {
|
||||
const lines = content.split('\n');
|
||||
const changeLog = [];
|
||||
const pin = /^## /;
|
||||
let begin = false;
|
||||
for (let i = 0; i < lines.length; i += 1) {
|
||||
const line = lines[i];
|
||||
if (begin && pin.test(line)) {
|
||||
break;
|
||||
}
|
||||
if (begin && line) {
|
||||
changeLog.push(line);
|
||||
}
|
||||
if (!begin) {
|
||||
begin = pin.test(line);
|
||||
if (begin) {
|
||||
tag = line.substring(3, line.length).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
return changeLog.join('\n\n');
|
||||
}
|
||||
|
||||
const changelogPath = path.join(__dirname, '..', CHANGELOG_NAME);
|
||||
const changelog = readFileSync(changelogPath, 'utf-8');
|
||||
|
||||
const body = getChangelog(changelog);
|
||||
|
||||
async function run() {
|
||||
const url = newGithubReleaseUrl({
|
||||
user,
|
||||
repo,
|
||||
tag,
|
||||
body: body,
|
||||
});
|
||||
|
||||
await open(url);
|
||||
|
||||
console.log(chalk.yellow('🚀 Please check tag and changelog. Then click publish!'));
|
||||
}
|
||||
|
||||
run();
|
71
scripts/tag.js
Normal file
71
scripts/tag.js
Normal file
@@ -0,0 +1,71 @@
|
||||
const chalk = require('chalk');
|
||||
const simpleGit = require('simple-git/promise');
|
||||
const { execSync } = require('child_process');
|
||||
const { readFileSync } = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const CHANGELOG_NAME = 'CHANGELOG.md';
|
||||
const CHANGELOG_PATH = path.join(__dirname, '..', CHANGELOG_NAME);
|
||||
const CHANGELOG = readFileSync(CHANGELOG_PATH, 'utf-8');
|
||||
|
||||
const cwd = process.cwd();
|
||||
const git = simpleGit(cwd);
|
||||
|
||||
async function run() {
|
||||
execSync(`git pull`);
|
||||
|
||||
const data = await git.tags();
|
||||
const tags = data.all;
|
||||
let tag = tags.reverse()[0];
|
||||
console.log(chalk.green(`[Git Query] tag: ${tag}`));
|
||||
|
||||
const tagChangelog = getChangelogTag(CHANGELOG);
|
||||
if (tagChangelog && tag != tagChangelog) {
|
||||
console.log(chalk.yellow(`[Git Action] Push new ${tagChangelog} tag!`));
|
||||
execSync(`git tag ${tagChangelog}`);
|
||||
execSync(`git push origin ${tagChangelog}:${tagChangelog}`);
|
||||
execSync(`git pull`);
|
||||
tag = tagChangelog;
|
||||
} else {
|
||||
console.log(chalk.yellow('🙄 Please add new release changelog first.'));
|
||||
console.log('');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const tagSimple = tag.startsWith('v') ? tag.substring(0, 2) : tag.substring(0, 1);
|
||||
console.log(chalk.green(`[Git Query] tagSimple: ${tagSimple}`));
|
||||
|
||||
if (tags.includes(tagSimple)) {
|
||||
console.log(chalk.yellow(`[Git Action] Delete ${tagSimple} tag`));
|
||||
execSync(`git push origin :refs/tags/${tagSimple}`);
|
||||
console.log(chalk.green(`[Git Action] Delete ${tagSimple} tag success`));
|
||||
}
|
||||
|
||||
console.log(chalk.yellow(`[Git Action] Add new simple ${tagSimple} tag`));
|
||||
execSync(`git push origin ${tag}:${tagSimple}`);
|
||||
console.log(chalk.green('🎉 Done!'));
|
||||
}
|
||||
|
||||
function getChangelogTag(content) {
|
||||
const lines = content.split('\n');
|
||||
const pin = /^## /;
|
||||
let begin = false;
|
||||
let tag = '';
|
||||
|
||||
for (let i = 0; i < lines.length; i += 1) {
|
||||
const line = lines[i];
|
||||
if (begin && pin.test(line)) {
|
||||
break;
|
||||
}
|
||||
if (!begin) {
|
||||
begin = pin.test(line);
|
||||
if (begin) {
|
||||
tag = line.substring(3, line.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tag.trim();
|
||||
}
|
||||
|
||||
run();
|
113
scripts/update-users.js
Normal file
113
scripts/update-users.js
Normal file
@@ -0,0 +1,113 @@
|
||||
const { readFileSync, writeFileSync } = require('fs');
|
||||
const { stripIndent } = require('common-tags');
|
||||
|
||||
// **************************************************************************
|
||||
|
||||
let { users } = require('../USERS.js');
|
||||
|
||||
users.sort((a, b) => getCurrentName(a).localeCompare(getCurrentName(b)));
|
||||
|
||||
// **************************************************************************
|
||||
const DEFAULT_WIDTH = 46;
|
||||
|
||||
// **************************************************************************
|
||||
let table = '';
|
||||
let row = users.length / 4;
|
||||
let lastNo = users.length % 4;
|
||||
if (lastNo != 0) row += 1;
|
||||
for (let j = 1; j <= row; j++) {
|
||||
let data = '';
|
||||
data = stripIndent`
|
||||
<tr>
|
||||
<td align="center" width="180">${getImg(users[(j - 1) * 4])}</td>
|
||||
<td align="center" width="180">${getImg(users[(j - 1) * 4 + 1])}</td>
|
||||
<td align="center" width="180">${getImg(users[(j - 1) * 4 + 2])}</td>
|
||||
<td align="center" width="180">${getImg(users[(j - 1) * 4 + 3])}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" width="180">${getName(users[(j - 1) * 4])}</td>
|
||||
<td align="center" width="180">${getName(users[(j - 1) * 4 + 1])}</td>
|
||||
<td align="center" width="180">${getName(users[(j - 1) * 4 + 2])}</td>
|
||||
<td align="center" width="180">${getName(users[(j - 1) * 4 + 3])}</td>
|
||||
</tr>
|
||||
`;
|
||||
table += data;
|
||||
}
|
||||
|
||||
table = `<table>
|
||||
${table}
|
||||
</table>
|
||||
|
||||
`;
|
||||
|
||||
// **************************************************************************
|
||||
|
||||
const point = '<table>';
|
||||
const cnPoint = `## 图标`;
|
||||
const enPoint = `## Badge`;
|
||||
const ReadmeCN = './README.zh-CN.md';
|
||||
const ReadmeEN = './README.md';
|
||||
|
||||
// **************************************************************************
|
||||
|
||||
const cn = readFileSync(ReadmeCN, 'utf8');
|
||||
const cnIn = cn.indexOf(point);
|
||||
const cnAfterIn = cn.indexOf(cnPoint);
|
||||
const cnBefore = cn.substring(0, cnIn);
|
||||
const cnAfter = cn.substring(cnAfterIn, cn.length);
|
||||
const newcn = cnBefore + table + cnAfter;
|
||||
writeFileSync(ReadmeCN, newcn);
|
||||
console.log(`🎉 Done cn`);
|
||||
|
||||
// **************************************************************************
|
||||
|
||||
const en = readFileSync(ReadmeEN, 'utf8');
|
||||
const enIn = en.indexOf(point);
|
||||
const enAfterIn = en.indexOf(enPoint);
|
||||
const enBefore = en.substring(0, enIn);
|
||||
const enAfter = en.substring(enAfterIn, en.length);
|
||||
const newen = enBefore + table + enAfter;
|
||||
writeFileSync(ReadmeEN, newen);
|
||||
console.log(`🎉 Done en`);
|
||||
|
||||
// **************************************************************************
|
||||
|
||||
function getImg(o) {
|
||||
if (o) {
|
||||
return `
|
||||
<a href="${o.url}">
|
||||
<img src="${o.logo}"${getImgWidth(o)}/>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
return ``;
|
||||
}
|
||||
|
||||
function getImgWidth(o) {
|
||||
if (o) {
|
||||
let width = o.width;
|
||||
if (width === 'auto') {
|
||||
width = '';
|
||||
} else {
|
||||
width = width ? width : DEFAULT_WIDTH;
|
||||
}
|
||||
return ` width="${width}"`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getName(o) {
|
||||
if (o) {
|
||||
return `<a href="${o.url}">${o.url.split('/').slice(-1)[0]}</a>`;
|
||||
}
|
||||
return ``;
|
||||
}
|
||||
|
||||
function getCurrentName(o) {
|
||||
if (o) {
|
||||
return o.url.split('/').slice(-1)[0];
|
||||
}
|
||||
return ``;
|
||||
}
|
||||
|
||||
// **************************************************************************
|
44
scripts/update-version.js
Normal file
44
scripts/update-version.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const { readFileSync, writeFileSync } = require('fs');
|
||||
|
||||
const last = /@v2/g;
|
||||
const now = `@v3`;
|
||||
|
||||
let readme = readFileSync('./README.md', 'utf-8');
|
||||
readme = readme.replace(last, now);
|
||||
writeFileSync('./README.md', readme);
|
||||
console.log('readme done!');
|
||||
|
||||
let readmeen = readFileSync('./README.en-US.md', 'utf-8');
|
||||
readmeen = readmeen.replace(last, now);
|
||||
writeFileSync('./README.en-US.md', readmeen);
|
||||
console.log('readmeen done!');
|
||||
|
||||
let index = readFileSync('./web/docs/index.md', 'utf-8');
|
||||
index = index.replace(last, now);
|
||||
writeFileSync('./web/docs/index.md', index);
|
||||
console.log('index done!');
|
||||
|
||||
let indexen = readFileSync('./web/docs/index.en-US.md', 'utf-8');
|
||||
indexen = indexen.replace(last, now);
|
||||
writeFileSync('./web/docs/index.en-US.md', indexen);
|
||||
console.log('indexen done!');
|
||||
|
||||
let base = readFileSync('./web/docs/base.md', 'utf-8');
|
||||
base = base.replace(last, now);
|
||||
writeFileSync('./web/docs/base.md', base);
|
||||
console.log('base done!');
|
||||
|
||||
let baseen = readFileSync('./web/docs/base.en-US.md', 'utf-8');
|
||||
baseen = baseen.replace(last, now);
|
||||
writeFileSync('./web/docs/base.en-US.md', baseen);
|
||||
console.log('baseen done!');
|
||||
|
||||
let adv = readFileSync('./web/docs/advanced.md', 'utf-8');
|
||||
adv = adv.replace(last, now);
|
||||
writeFileSync('./web/docs/advanced.md', adv);
|
||||
console.log('adv done!');
|
||||
|
||||
let adven = readFileSync('./web/docs/advanced.en-US.md', 'utf-8');
|
||||
adven = adven.replace(last, now);
|
||||
writeFileSync('./web/docs/advanced.en-US.md', adven);
|
||||
console.log('adven done!');
|
222
src/advanced.js
222
src/advanced.js
@@ -1,222 +0,0 @@
|
||||
require('dotenv').config();
|
||||
const core = require("@actions/core");
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
|
||||
var dayjs = require('dayjs');
|
||||
var utc = require('dayjs/plugin/utc');
|
||||
dayjs.extend(utc);
|
||||
var isSameOrBefore = require('dayjs/plugin/isSameOrBefore');
|
||||
dayjs.extend(isSameOrBefore);
|
||||
|
||||
const {
|
||||
doAddLabels,
|
||||
doCloseIssue,
|
||||
doCreateComment,
|
||||
doLockIssue
|
||||
} = require('./base.js');
|
||||
|
||||
const { dealInput, matchKeyword } = require('./util.js');
|
||||
|
||||
const token = core.getInput('token');
|
||||
const octokit = new Octokit({ auth: `token ${token}` });
|
||||
|
||||
let direction = core.getInput("direction");
|
||||
direction = direction === 'desc' ? 'desc' : 'asc';
|
||||
|
||||
const commentAuth = core.getInput("comment-auth");
|
||||
const bodyIncludes = core.getInput('body-includes');
|
||||
const titleIncludes = core.getInput('title-includes');
|
||||
const assigneeIncludes = core.getInput('assignee-includes');
|
||||
|
||||
const issueCreator = core.getInput("issue-creator");
|
||||
const issueAssignee = core.getInput('issue-assignee');
|
||||
const issueMentioned = core.getInput('issue-mentioned');
|
||||
|
||||
let issueState = core.getInput("issue-state") || 'all';
|
||||
|
||||
if (issueState != 'open' && issueState != 'closed') {
|
||||
issueState = 'all';
|
||||
}
|
||||
|
||||
const inactiveDay = core.getInput("inactive-day");
|
||||
const inactiveLabel = core.getInput("inactive-label") || 'inactive';
|
||||
|
||||
async function doCheckInactive (owner, repo, labels) {
|
||||
const issues = await doQueryIssues(owner, repo, labels, issueState);
|
||||
|
||||
if (issues.length) {
|
||||
for (let i = 0; i < issues.length; i++) {
|
||||
if (!JSON.stringify(issues[i].labels).includes(inactiveLabel)) {
|
||||
await doAddLabels(owner, repo, issues[i].number, inactiveLabel);
|
||||
if (core.getInput("body")) {
|
||||
await doCreateComment(owner, repo, issues[i].number, core.getInput("body"));
|
||||
}
|
||||
} else {
|
||||
core.info(`Actions: [add-inactive] issue ${issues[i].number} has label!`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
core.info(`Actions: [query-issues] empty!`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查 issue 是否满足条件,满足返回 true
|
||||
* 当前 issue 的指定人是否有一个满足 assigneeIncludes 里的某个
|
||||
* 关键字匹配,是否包含前一个某个+后一个某个 '官网,网站/挂了,无法访问'
|
||||
*/
|
||||
async function doCheckIssue (owner, repo, issueNumber) {
|
||||
var checkResult = true;
|
||||
const issue = await octokit.issues.get({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber
|
||||
});
|
||||
|
||||
if (!!checkResult && assigneeIncludes) {
|
||||
let assigneesCheck = dealInput(assigneeIncludes);
|
||||
let checkAssignee = false;
|
||||
issue.data.assignees.forEach(it => {
|
||||
if (checkResult && !checkAssignee && assigneesCheck.includes(it.login)) {
|
||||
checkResult = true;
|
||||
checkAssignee = true;
|
||||
}
|
||||
})
|
||||
!checkAssignee ? checkResult = false : null;
|
||||
}
|
||||
|
||||
if (!!checkResult && titleIncludes) {
|
||||
const titleArr = titleIncludes.split('/');
|
||||
const keyword1 = dealInput(titleArr[0]);
|
||||
const keyword2 = dealInput(titleArr[1]);
|
||||
checkResult =
|
||||
keyword2.length ?
|
||||
matchKeyword(issue.data.title, keyword1) && matchKeyword(issue.data.title, keyword2) :
|
||||
matchKeyword(issue.data.title, keyword1);
|
||||
}
|
||||
|
||||
if (!!checkResult && bodyIncludes) {
|
||||
const bodyArr = bodyIncludes.split('/');
|
||||
const keyword1 = dealInput(bodyArr[0]);
|
||||
const keyword2 = dealInput(bodyArr[1]);
|
||||
checkResult =
|
||||
keyword2.length ?
|
||||
matchKeyword(issue.data.body, keyword1) && matchKeyword(issue.data.body, keyword2) :
|
||||
matchKeyword(issue.data.body, keyword1);
|
||||
}
|
||||
core.info(`Actions: [check-issue][${!!checkResult}] success!`);
|
||||
core.setOutput("check-result", !!checkResult);
|
||||
};
|
||||
|
||||
async function doCloseIssues (owner, repo, labels) {
|
||||
const issues = await doQueryIssues(owner, repo, labels, 'open');
|
||||
|
||||
if (issues.length) {
|
||||
for (let i = 0; i < issues.length; i++) {
|
||||
await doCloseIssue(owner, repo, issues[i].number);
|
||||
if (core.getInput("body")) {
|
||||
await doCreateComment(owner, repo, issues[i].number, core.getInput("body"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
core.info(`Actions: [query-issues] empty!`);
|
||||
}
|
||||
};
|
||||
|
||||
async function doFindComments (owner, repo, issueNumber) {
|
||||
const res = await octokit.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber
|
||||
});
|
||||
core.info(`Actions: [find-comments][${issueNumber}] success!`);
|
||||
let comments = [];
|
||||
res.data.forEach(item => {
|
||||
const a = commentAuth ? item.user.login === commentAuth : true;
|
||||
const b = bodyIncludes ? item.body.includes(bodyIncludes) : true;
|
||||
if (a && b) {
|
||||
comments.push({
|
||||
id: item.id,
|
||||
auth: item.user.login,
|
||||
body: item.body,
|
||||
created: item.created_at,
|
||||
updated: item.updated_at
|
||||
})
|
||||
if (direction === 'desc') {
|
||||
comments.reverse();
|
||||
}
|
||||
}
|
||||
})
|
||||
core.setOutput("comments", comments);
|
||||
};
|
||||
|
||||
async function doLockIssues (owner, repo, labels) {
|
||||
const issues = await doQueryIssues(owner, repo, labels, issueState);
|
||||
|
||||
if (issues.length) {
|
||||
for (let i = 0; i < issues.length; i++) {
|
||||
await doLockIssue(owner, repo, issues[i].number);
|
||||
if (core.getInput("body")) {
|
||||
await doCreateComment(owner, repo, issues[i].number, core.getInput("body"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
core.info(`Actions: [query-issues] empty!`);
|
||||
}
|
||||
};
|
||||
|
||||
async function doQueryIssues (owner, repo, labels, state, creator) {
|
||||
let params = {
|
||||
owner,
|
||||
repo,
|
||||
state,
|
||||
};
|
||||
|
||||
issueCreator ? params.creator = issueCreator : null;
|
||||
issueAssignee ? params.assignee = issueAssignee : null;
|
||||
issueMentioned ? params.mentioned = issueMentioned : null;
|
||||
|
||||
if (labels) {
|
||||
params.labels = labels;
|
||||
}
|
||||
|
||||
if (creator) {
|
||||
params.creator = creator;
|
||||
}
|
||||
|
||||
const res = await octokit.issues.listForRepo(params);
|
||||
let issues = [];
|
||||
res.data.forEach(iss => {
|
||||
const a = bodyIncludes ? iss.body.includes(bodyIncludes) : true;
|
||||
const b = titleIncludes ? iss.title.includes(titleIncludes) : true;
|
||||
/**
|
||||
* Note: GitHub's REST API v3 considers every pull request an issue, but not every issue is a pull request.
|
||||
* For this reason, "Issues" endpoints may return both issues and pull requests in the response.
|
||||
* You can identify pull requests by the pull_request key.
|
||||
*/
|
||||
if (a && b && iss.pull_request === undefined) {
|
||||
if (inactiveDay && typeof(inactiveDay) === 'number') {
|
||||
let lastTime = dayjs.utc().subtract(inactiveDay, 'day');
|
||||
let updateTime = dayjs.utc(iss.updated_at);
|
||||
if (updateTime.isSameOrBefore(lastTime)) {
|
||||
issues.push(iss);
|
||||
}
|
||||
} else {
|
||||
issues.push(iss);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return issues;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
doCheckInactive,
|
||||
doCheckIssue,
|
||||
doCloseIssues,
|
||||
doFindComments,
|
||||
doLockIssues,
|
||||
|
||||
// tool
|
||||
doQueryIssues,
|
||||
};
|
367
src/base.js
367
src/base.js
@@ -1,367 +0,0 @@
|
||||
require('dotenv').config();
|
||||
const core = require("@actions/core");
|
||||
const github = require("@actions/github");
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
|
||||
const { doQueryIssues } = require('./advanced.js');
|
||||
|
||||
const ALLREACTIONS = [
|
||||
"+1",
|
||||
"-1",
|
||||
"laugh",
|
||||
"confused",
|
||||
"heart",
|
||||
"hooray",
|
||||
"rocket",
|
||||
"eyes",
|
||||
];
|
||||
|
||||
const { dealInput } = require('./util.js');
|
||||
|
||||
const token = core.getInput('token');
|
||||
const octokit = new Octokit({ auth: `token ${token}` });
|
||||
|
||||
const contents = core.getInput("contents");
|
||||
const issueContents = core.getInput("issue-contents");
|
||||
|
||||
async function doAddAssignees (owner, repo, issueNumber, assignees) {
|
||||
await octokit.issues.addAssignees({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
assignees: dealInput(assignees)
|
||||
});
|
||||
core.info(`Actions: [add-assignees][${assignees}] success!`);
|
||||
};
|
||||
|
||||
async function doAddLabels (owner, repo, issueNumber, labels) {
|
||||
await octokit.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
labels: dealInput(labels)
|
||||
});
|
||||
core.info(`Actions: [add-labels][${labels}] success!`);
|
||||
};
|
||||
|
||||
async function doCloseIssue (owner, repo, issueNumber) {
|
||||
await octokit.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
state: 'closed'
|
||||
});
|
||||
core.info(`Actions: [close-issue][${issueNumber}] success!`);
|
||||
};
|
||||
|
||||
async function doCreateComment (owner, repo, issueNumber, body) {
|
||||
const { data } = await octokit.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
body
|
||||
});
|
||||
core.info(`Actions: [create-comment][${body}] success!`);
|
||||
core.setOutput("comment-id", data.id);
|
||||
|
||||
if (contents) {
|
||||
await doCreateCommentContent(owner, repo, data.id, dealInput(contents));
|
||||
}
|
||||
};
|
||||
|
||||
async function doCreateCommentContent(owner, repo, commentId, contents) {
|
||||
if (contents.length) {
|
||||
contents.forEach(async item => {
|
||||
if (testContent(item)) {
|
||||
await octokit.reactions.createForIssueComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId,
|
||||
content: item
|
||||
});
|
||||
core.info(`Actions: [create-reactions][${item}] success!`);
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
async function doCreateIssue (owner, repo, title, body, labels, assignees) {
|
||||
let params = {
|
||||
owner,
|
||||
repo,
|
||||
title,
|
||||
body,
|
||||
labels: dealInput(labels),
|
||||
assignees: dealInput(assignees),
|
||||
};
|
||||
|
||||
const { data } = await octokit.issues.create(params);
|
||||
core.info(`Actions: [create-issue][${title}] success!`);
|
||||
core.setOutput("issue-number", data.number);
|
||||
|
||||
if (contents) {
|
||||
await doCreateIssueContent(owner, repo, data.number, dealInput(contents));
|
||||
}
|
||||
};
|
||||
|
||||
async function doCreateIssueContent(owner, repo, issueNumber, contents) {
|
||||
if (contents.length) {
|
||||
contents.forEach(async item => {
|
||||
if (testContent(item)) {
|
||||
await octokit.reactions.createForIssue({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
content: item
|
||||
});
|
||||
core.info(`Actions: [create-reactions][${item}] success!`);
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
async function doDeleteComment (owner, repo, commentId) {
|
||||
await octokit.issues.deleteComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId
|
||||
});
|
||||
core.info(`Actions: [delete-comment][${commentId}] success!`);
|
||||
};
|
||||
|
||||
async function doLockIssue (owner, repo, issueNumber) {
|
||||
await octokit.issues.lock({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
core.info(`Actions: [lock-issue][${issueNumber}] success!`);
|
||||
};
|
||||
|
||||
async function doOpenIssue (owner, repo, issueNumber) {
|
||||
await octokit.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
state: 'open'
|
||||
});
|
||||
core.info(`Actions: [open-issue][${issueNumber}] success!`);
|
||||
};
|
||||
|
||||
async function doRemoveAssignees (owner, repo, issueNumber, assignees) {
|
||||
await octokit.issues.removeAssignees({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
assignees: dealInput(assignees),
|
||||
});
|
||||
core.info(`Actions: [remove-assignees][${assignees}] success!`);
|
||||
};
|
||||
|
||||
async function doRemoveLabels (owner, repo, issueNumber, labels) {
|
||||
const issue = await octokit.issues.get({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber
|
||||
});
|
||||
const dealLabels = dealInput(labels);
|
||||
let addLables = [];
|
||||
if (dealLabels.length) {
|
||||
issue.data.labels.forEach(item => {
|
||||
!dealLabels.includes(item.name) ? addLables.push(item.name) : '';
|
||||
})
|
||||
await octokit.issues.setLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
labels: addLables
|
||||
});
|
||||
core.info(`Actions: [remove-labels][${labels}] success!`);
|
||||
}
|
||||
};
|
||||
|
||||
async function doSetLabels (owner, repo, issueNumber, labels) {
|
||||
await octokit.issues.setLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
labels: dealInput(labels)
|
||||
});
|
||||
core.info(`Actions: [set-labels][${labels}] success!`);
|
||||
};
|
||||
|
||||
async function doUnlockIssue (owner, repo, issueNumber) {
|
||||
await octokit.issues.unlock({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
core.info(`Actions: [unlock-issue][${issueNumber}] success!`);
|
||||
};
|
||||
|
||||
async function doUpdateComment (
|
||||
owner,
|
||||
repo,
|
||||
commentId,
|
||||
body,
|
||||
updateMode
|
||||
) {
|
||||
const comment = await octokit.issues.getComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId
|
||||
})
|
||||
const comment_body = comment.data.body;
|
||||
|
||||
let params = {
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId
|
||||
};
|
||||
|
||||
if (core.getInput("body")) {
|
||||
if (updateMode === 'append') {
|
||||
params.body = `${comment_body}\n${body}`;
|
||||
} else {
|
||||
params.body = body;
|
||||
}
|
||||
|
||||
await octokit.issues.updateComment(params);
|
||||
core.info(`Actions: [update-comment][${commentId}] success!`);
|
||||
}
|
||||
|
||||
if (contents) {
|
||||
await doCreateCommentContent(owner, repo, commentId, dealInput(contents));
|
||||
}
|
||||
};
|
||||
|
||||
async function doUpdateIssue (
|
||||
owner,
|
||||
repo,
|
||||
issueNumber,
|
||||
state,
|
||||
title,
|
||||
body,
|
||||
updateMode,
|
||||
assignees,
|
||||
labels
|
||||
) {
|
||||
const issue = await octokit.issues.get({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber
|
||||
})
|
||||
const issue_body = issue.data.body;
|
||||
const issue_title = issue.data.title;
|
||||
|
||||
let issue_labels = [];
|
||||
if (issue.data.labels.length > 0) {
|
||||
issue.data.labels.forEach(it =>{
|
||||
issue_labels.push(it.name);
|
||||
});
|
||||
}
|
||||
|
||||
let issue_assignees = [];
|
||||
if (issue.data.assignees.length > 0) {
|
||||
issue.data.assignees.forEach(it =>{
|
||||
issue_assignees.push(it.login);
|
||||
});
|
||||
}
|
||||
|
||||
let params = {
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
state
|
||||
};
|
||||
|
||||
params.title = core.getInput("title") ? title : issue_title;
|
||||
|
||||
let next_body;
|
||||
if (core.getInput("body")) {
|
||||
if (updateMode === 'append') {
|
||||
next_body = `${issue_body}\n${body}`;
|
||||
} else {
|
||||
next_body = body;
|
||||
}
|
||||
} else {
|
||||
next_body = issue_body;
|
||||
}
|
||||
params.body = next_body;
|
||||
|
||||
params.labels = labels ? dealInput(labels) : issue_labels;
|
||||
params.assignees = assignees ? dealInput(assignees) : issue_assignees;
|
||||
|
||||
await octokit.issues.update(params);
|
||||
core.info(`Actions: [update-issue][${issueNumber}] success!`);
|
||||
|
||||
if (contents) {
|
||||
await doCreateIssueContent(owner, repo, issueNumber, contents);
|
||||
}
|
||||
};
|
||||
|
||||
async function doWelcome (owner, repo, assignees, labels, body) {
|
||||
const context = github.context;
|
||||
const isIssue = !!context.payload.issue;
|
||||
if (!isIssue) {
|
||||
core.setFailed("The event that triggered this action must be a issue. Error!");
|
||||
} else {
|
||||
const auth = context.payload.sender.login;
|
||||
core.info(`Actions: [welcome: auth=][${auth}]`);
|
||||
const issueNumber = context.issue.number;
|
||||
const creator = 'zoo-js-bot';
|
||||
const issues = await doQueryIssues(owner, repo, false, 'all', creator);
|
||||
if (issues.length == 0 || (issues.length == 1 && issues[0].number == issueNumber)) {
|
||||
if (core.getInput("body")) {
|
||||
await doCreateComment(owner, repo, issueNumber, body);
|
||||
} else {
|
||||
core.info(`Actions: [welcome] no body!`);
|
||||
}
|
||||
|
||||
if (assignees) {
|
||||
await doAddAssignees(owner, repo, issueNumber, assignees);
|
||||
}
|
||||
|
||||
if (labels) {
|
||||
await doAddLabels(owner, repo, issueNumber, labels);
|
||||
}
|
||||
|
||||
if (issueContents) {
|
||||
await doCreateIssueContent(owner, repo, issueNumber, dealInput(issueContents));
|
||||
}
|
||||
} else {
|
||||
core.info(`Actions: [welcome][${auth}] is not first time!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// tool
|
||||
function testContent(con) {
|
||||
if (ALLREACTIONS.includes(con)) {
|
||||
return true;
|
||||
} else {
|
||||
core.setFailed("This actions not supported!");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// exports
|
||||
module.exports = {
|
||||
doAddAssignees,
|
||||
doAddLabels,
|
||||
doCloseIssue,
|
||||
doCreateComment,
|
||||
doCreateCommentContent,
|
||||
doCreateIssue,
|
||||
doCreateIssueContent,
|
||||
doDeleteComment,
|
||||
doLockIssue,
|
||||
doOpenIssue,
|
||||
doRemoveAssignees,
|
||||
doRemoveLabels,
|
||||
doSetLabels,
|
||||
doUnlockIssue,
|
||||
doUpdateComment,
|
||||
doUpdateIssue,
|
||||
doWelcome,
|
||||
};
|
7
src/core/README.md
Normal file
7
src/core/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# `@actions/core`
|
||||
|
||||
## Web
|
||||
|
||||
- https://github.com/actions/toolkit/tree/main/packages/core
|
||||
|
||||

|
29
src/core/index.ts
Normal file
29
src/core/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import * as core from '@actions/core';
|
||||
|
||||
export const baseInfo = (mess: string) => {
|
||||
core.info(mess);
|
||||
};
|
||||
|
||||
export const info = (mess: string) => {
|
||||
core.info(`[📝 AC] ${mess}`);
|
||||
};
|
||||
|
||||
export const error = (mess: string) => {
|
||||
core.error(`[💥 AC] ${mess}`);
|
||||
};
|
||||
|
||||
export const notice = (mess: string) => {
|
||||
core.notice(`[🏷 AC] ${mess}`);
|
||||
};
|
||||
|
||||
export const warning = (mess: string) => {
|
||||
core.warning(`[🎃 AC] ${mess}`);
|
||||
};
|
||||
|
||||
export const getInput = core.getInput;
|
||||
|
||||
export const setOutput = core.setOutput;
|
||||
|
||||
export const setFailed = (mess: string) => {
|
||||
core.setFailed(`[🚨 AC] ${mess}`);
|
||||
};
|
430
src/helper/advanced.ts
Normal file
430
src/helper/advanced.ts
Normal file
@@ -0,0 +1,430 @@
|
||||
import type { TPermissionType } from 'actions-util';
|
||||
import { checkPermission, dealStringToArr } from 'actions-util';
|
||||
import dayjs from 'dayjs';
|
||||
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
|
||||
import * as core from '../core';
|
||||
import type { IIssueCoreEngine, IListIssuesParams, TCommentInfo, TIssueList } from '../issue';
|
||||
import { EConst } from '../shared';
|
||||
import type { TCloseReason, TEmoji, TIssueState, TOutList } from '../types';
|
||||
import { checkDuplicate, matchKeyword, replaceStr2Arr } from '../util';
|
||||
import {
|
||||
doAddAssignees,
|
||||
doAddLabels,
|
||||
doCloseIssue,
|
||||
doCreateComment,
|
||||
doCreateCommentEmoji,
|
||||
doLockIssue,
|
||||
doRemoveLabels,
|
||||
doSetLabels,
|
||||
doUpdateComment,
|
||||
} from './base';
|
||||
|
||||
let ICE: IIssueCoreEngine;
|
||||
export function initAdvancedICE(_ICE: IIssueCoreEngine) {
|
||||
ICE = _ICE;
|
||||
}
|
||||
|
||||
export async function doQueryIssues(
|
||||
state: TIssueState | 'all',
|
||||
creator?: string,
|
||||
ignoreLabels?: boolean,
|
||||
): Promise<TIssueList> {
|
||||
const params = {
|
||||
state,
|
||||
} as IListIssuesParams;
|
||||
|
||||
const issueCreator = core.getInput('issue-creator');
|
||||
const issueAssignee = core.getInput('issue-assignee');
|
||||
const issueMentioned = core.getInput('issue-mentioned');
|
||||
|
||||
if (issueCreator) params.creator = issueCreator;
|
||||
if (issueAssignee) params.assignee = issueAssignee;
|
||||
if (issueMentioned) params.mentioned = issueMentioned;
|
||||
|
||||
const labels = core.getInput('labels');
|
||||
|
||||
if (labels && !ignoreLabels) params.labels = labels;
|
||||
|
||||
if (creator) params.creator = creator;
|
||||
|
||||
const issuesList = await ICE.listIssues(params);
|
||||
const issues: TIssueList = [];
|
||||
const issueNumbers: number[] = [];
|
||||
|
||||
if (issuesList.length) {
|
||||
const excludeLabels = core.getInput('exclude-labels') || '';
|
||||
const bodyIncludes = core.getInput('body-includes');
|
||||
const titleIncludes = core.getInput('title-includes');
|
||||
|
||||
const excludeLabelsArr = dealStringToArr(excludeLabels);
|
||||
issuesList.forEach(async issue => {
|
||||
const bodyCheck = bodyIncludes ? issue.body.includes(bodyIncludes) : true;
|
||||
const titleCheck = titleIncludes ? issue.title.includes(titleIncludes) : true;
|
||||
/**
|
||||
* Note: GitHub's REST API v3 considers every pull request an issue, but not every issue is a pull request.
|
||||
* For this reason, "Issues" endpoints may return both issues and pull requests in the response.
|
||||
* You can identify pull requests by the pull_request key.
|
||||
*/
|
||||
if (bodyCheck && titleCheck && issue.pull_request === undefined) {
|
||||
if (excludeLabelsArr.length) {
|
||||
if (issue.labels.length) {
|
||||
for (let i = 0; i < issue.labels.length; i += 1) {
|
||||
if (excludeLabelsArr.includes(issue.labels[i].name)) return;
|
||||
}
|
||||
} else {
|
||||
if (excludeLabelsArr.includes(EConst.ExcludeEmpty)) return;
|
||||
}
|
||||
}
|
||||
|
||||
const inactiveDay = core.getInput('inactive-day');
|
||||
if (inactiveDay) {
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(isSameOrBefore);
|
||||
|
||||
const lastTime = dayjs.utc().subtract(+inactiveDay, 'day');
|
||||
|
||||
const inactiveMode = core.getInput('inactive-mode') || 'issue';
|
||||
let updateTime = dayjs.utc(issue.updated_at);
|
||||
if (inactiveMode === 'comment') {
|
||||
ICE.setIssueNumber(issue.number);
|
||||
const comments = await ICE.listComments();
|
||||
if (comments.length) {
|
||||
updateTime = dayjs.utc(comments[comments.length - 1].updated_at);
|
||||
}
|
||||
}
|
||||
if (updateTime && updateTime.isSameOrBefore(lastTime)) {
|
||||
issues.push(issue);
|
||||
issueNumbers.push(issue.number);
|
||||
}
|
||||
} else {
|
||||
issues.push(issue);
|
||||
issueNumbers.push(issue.number);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
core.info(`[doQueryIssues] issueNumbers is ---> ${JSON.stringify(issueNumbers)}`);
|
||||
return issues;
|
||||
}
|
||||
|
||||
export async function doCheckInactive(body: string, emoji?: string) {
|
||||
let issueState = core.getInput('issue-state');
|
||||
if (issueState !== 'all' && issueState !== 'closed') {
|
||||
issueState = 'open';
|
||||
}
|
||||
const issues = await doQueryIssues(issueState as TIssueState | 'all');
|
||||
if (issues.length) {
|
||||
const inactiveLabel = core.getInput('inactive-label') || 'inactive';
|
||||
for (const issue of issues) {
|
||||
const { labels, number } = issue;
|
||||
const labelNames = labels.map(({ name }) => name);
|
||||
if (!labelNames.includes(inactiveLabel)) {
|
||||
core.info(`[doCheckInactive] Doing ---> ${number}`);
|
||||
await doAddLabels([inactiveLabel], number);
|
||||
if (body) await doCreateComment(body, emoji, number);
|
||||
} else {
|
||||
core.info(`[doCheckInactive] The issue ${number} already has ${inactiveLabel} label!`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
core.info(`[doCheckInactive] Query issues empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 issue 是否满足条件,满足返回 true
|
||||
* 当前 issue 的指定人是否有一个满足 assigneeIncludes 里的某个
|
||||
* 关键字匹配,是否包含前一个某个+后一个某个 '官网,网站/挂了,无法访问'
|
||||
*/
|
||||
export async function doCheckIssue() {
|
||||
let checkResult = true;
|
||||
|
||||
const issue = await ICE.getIssue();
|
||||
const assigneeIncludes = core.getInput('assignee-includes');
|
||||
|
||||
if (assigneeIncludes) {
|
||||
const assigneesCheck = dealStringToArr(assigneeIncludes);
|
||||
let checkAssignee = false;
|
||||
issue.assignees.forEach(it => {
|
||||
if (checkResult && !checkAssignee && assigneesCheck.includes(it.login)) {
|
||||
checkResult = true;
|
||||
checkAssignee = true;
|
||||
}
|
||||
});
|
||||
if (!checkAssignee) checkResult = false;
|
||||
}
|
||||
|
||||
const titleRemove = core.getInput('title-excludes');
|
||||
if (!!checkResult && titleRemove) {
|
||||
const removes = dealStringToArr(titleRemove);
|
||||
let t = issue.title;
|
||||
removes.forEach(re => {
|
||||
t = t.replace(re, '');
|
||||
});
|
||||
if (t.trim().length == 0) {
|
||||
checkResult = false;
|
||||
}
|
||||
}
|
||||
|
||||
const titleIncludes = core.getInput('title-includes');
|
||||
if (!!checkResult && titleIncludes) {
|
||||
const titleArr = titleIncludes.split('/');
|
||||
const keyword1 = dealStringToArr(titleArr[0]);
|
||||
const keyword2 = dealStringToArr(titleArr[1]);
|
||||
checkResult = keyword2.length
|
||||
? matchKeyword(issue.title, keyword1) && matchKeyword(issue.title, keyword2)
|
||||
: matchKeyword(issue.title, keyword1);
|
||||
}
|
||||
|
||||
const bodyIncludes = core.getInput('body-includes');
|
||||
if (!!checkResult && bodyIncludes) {
|
||||
const bodyArr = bodyIncludes.split('/');
|
||||
const keyword1 = dealStringToArr(bodyArr[0]);
|
||||
const keyword2 = dealStringToArr(bodyArr[1]);
|
||||
checkResult =
|
||||
keyword2 && keyword2.length
|
||||
? matchKeyword(issue.body, keyword1) && matchKeyword(issue.body, keyword2)
|
||||
: matchKeyword(issue.body, keyword1);
|
||||
}
|
||||
|
||||
core.info(`[doCheckIssue] result is [${checkResult}]`);
|
||||
core.setOutput('check-result', checkResult);
|
||||
}
|
||||
|
||||
export async function doCloseIssues(body: string, closeReason: TCloseReason, emoji?: string) {
|
||||
const issues = await doQueryIssues('open');
|
||||
if (issues.length) {
|
||||
for (const { number } of issues) {
|
||||
core.info(`[doCloseIssues] Doing ---> ${number}`);
|
||||
if (body) await doCreateComment(body, emoji, number);
|
||||
await doCloseIssue(closeReason, number);
|
||||
}
|
||||
} else {
|
||||
core.info(`[doCloseIssues] Query issues empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doFindComments() {
|
||||
const commentList = await ICE.listComments();
|
||||
core.info(`[doFindComments] success!`);
|
||||
|
||||
const comments: TOutList = [];
|
||||
|
||||
if (commentList.length) {
|
||||
const commentAuth = core.getInput('comment-auth');
|
||||
const bodyIncludes = core.getInput('body-includes');
|
||||
const direction = core.getInput('direction') === 'desc' ? 'desc' : 'asc';
|
||||
for (const comment of commentList) {
|
||||
const checkUser = commentAuth ? comment.user.login === commentAuth : true;
|
||||
const checkBody = bodyIncludes ? comment.body.includes(bodyIncludes) : true;
|
||||
if (checkUser && checkBody) {
|
||||
comments.push({
|
||||
id: comment.id,
|
||||
auth: comment.user.login,
|
||||
body: comment.body,
|
||||
created: comment.created_at,
|
||||
updated: comment.updated_at,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (direction === 'desc') {
|
||||
comments.reverse();
|
||||
}
|
||||
core.setOutput('comments', JSON.stringify(comments));
|
||||
core.info(`[doFindComments] comments --> ${JSON.stringify(comments)}`);
|
||||
} else {
|
||||
core.info(`[doFindComments] Query comments empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doFindIssues() {
|
||||
let issueState = core.getInput('issue-state');
|
||||
if (issueState !== 'all' && issueState !== 'closed') {
|
||||
issueState = 'open';
|
||||
}
|
||||
const issueList = await doQueryIssues(issueState as TIssueState | 'all');
|
||||
let issues: TOutList = [];
|
||||
if (issueList.length) {
|
||||
const direction = core.getInput('direction') === 'desc' ? 'desc' : 'asc';
|
||||
issues = issueList.map(issue => {
|
||||
return {
|
||||
auth: issue.user.login,
|
||||
number: issue.number,
|
||||
title: issue.title,
|
||||
body: issue.body,
|
||||
state: issue.state,
|
||||
created: issue.created_at,
|
||||
updated: issue.updated_at,
|
||||
};
|
||||
});
|
||||
if (direction === 'desc') {
|
||||
issues.reverse();
|
||||
}
|
||||
core.info(`[doFindIssues] issues --> ${JSON.stringify(issues)}`);
|
||||
} else {
|
||||
core.info(`[doFindIssues] Query issues empty!`);
|
||||
}
|
||||
core.setOutput('issues', JSON.stringify(issues));
|
||||
}
|
||||
|
||||
export async function doLockIssues(body: string, emoji?: string) {
|
||||
let issueState = core.getInput('issue-state');
|
||||
if (issueState !== 'all' && issueState !== 'closed') {
|
||||
issueState = 'open';
|
||||
}
|
||||
const issues = await doQueryIssues(issueState as TIssueState | 'all');
|
||||
|
||||
if (issues.length) {
|
||||
for (const { number } of issues) {
|
||||
core.info(`[doLockIssues] Doing ---> ${number}`);
|
||||
if (body) await doCreateComment(body, emoji, number);
|
||||
await doLockIssue(number);
|
||||
}
|
||||
} else {
|
||||
core.info(`[doLockIssues] Query issues empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doMarkAssignees(comment: TCommentInfo) {
|
||||
const assignCommand = core.getInput('assign-command') || '/assign';
|
||||
if (comment.body.startsWith(assignCommand)) {
|
||||
const { body, user } = comment;
|
||||
const assigns = replaceStr2Arr(body, assignCommand, '@');
|
||||
const requirePermission = core.getInput('require-permission') || 'write';
|
||||
const permission = await ICE.getUserPermission(user.login);
|
||||
if (!checkPermission(requirePermission as TPermissionType, permission)) {
|
||||
core.info(`[doMarkAssignees] The user ${user.login} is not allow!`);
|
||||
return;
|
||||
}
|
||||
await doAddAssignees(assigns);
|
||||
core.info(`[doMarkAssignees] Done!`);
|
||||
} else {
|
||||
core.info(`[doMarkAssignees] The issues ignore!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doMarkDuplicate(
|
||||
comment: TCommentInfo,
|
||||
closeReason: TCloseReason,
|
||||
labels?: string[] | void,
|
||||
emoji?: string,
|
||||
) {
|
||||
const duplicateCommand = core.getInput('duplicate-command');
|
||||
const duplicateLabels = core.getInput('duplicate-labels');
|
||||
const removeLables = core.getInput('remove-labels') || '';
|
||||
const closeIssue = core.getInput('close-issue');
|
||||
const requirePermission = core.getInput('require-permission') || 'write';
|
||||
|
||||
const commentId = comment.id;
|
||||
const commentBody = comment.body;
|
||||
const commentUser = comment.user.login;
|
||||
|
||||
const ifCommandInput = !!duplicateCommand;
|
||||
|
||||
if (
|
||||
!commentBody.includes('?') &&
|
||||
((ifCommandInput &&
|
||||
commentBody.startsWith(duplicateCommand) &&
|
||||
commentBody.split(' ')[0] == duplicateCommand) ||
|
||||
checkDuplicate(commentBody))
|
||||
) {
|
||||
const permission = await ICE.getUserPermission(commentUser);
|
||||
if (!checkPermission(requirePermission as TPermissionType, permission)) {
|
||||
core.info(`[doMarkDuplicate] The user ${commentUser} is not allow!`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ifCommandInput) {
|
||||
const nextBody = commentBody.replace(duplicateCommand, 'Duplicate of');
|
||||
await doUpdateComment(commentId, nextBody, 'replace', emoji);
|
||||
} else if (emoji) {
|
||||
await doCreateCommentEmoji(commentId, emoji);
|
||||
}
|
||||
|
||||
const issue = await ICE.getIssue();
|
||||
let newLabels: string[] = [];
|
||||
if (issue.labels.length > 0) {
|
||||
newLabels = issue.labels
|
||||
.map(({ name }) => name)
|
||||
.filter(name => !dealStringToArr(removeLables).includes(name));
|
||||
}
|
||||
if (duplicateLabels) {
|
||||
newLabels = [...newLabels, ...dealStringToArr(duplicateLabels)];
|
||||
}
|
||||
if (labels?.length) {
|
||||
newLabels = [...labels];
|
||||
}
|
||||
if (newLabels.length > 0) {
|
||||
await doSetLabels(newLabels);
|
||||
}
|
||||
if (closeIssue === 'true') {
|
||||
await doCloseIssue(closeReason);
|
||||
}
|
||||
core.info(`[doMarkDuplicate] Done!`);
|
||||
} else {
|
||||
core.warning(
|
||||
`This comment body should start with 'duplicate-command' or 'Duplicate of' and not include '?'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doToggleLabels(labels: string[] = []) {
|
||||
const issue = await ICE.getIssue();
|
||||
const baseLabels: string[] = issue.labels.map(({ name }: any) => name);
|
||||
|
||||
const addLabels = [];
|
||||
const removeLabels = [];
|
||||
|
||||
for (const label of labels) {
|
||||
if (baseLabels.includes(label)) {
|
||||
removeLabels.push(label);
|
||||
} else {
|
||||
addLabels.push(label);
|
||||
}
|
||||
}
|
||||
|
||||
if (removeLabels.length) {
|
||||
await doRemoveLabels(removeLabels);
|
||||
}
|
||||
|
||||
if (addLabels.length) {
|
||||
await doAddLabels(addLabels);
|
||||
}
|
||||
|
||||
core.info(`[doToggleLabels] Done!`);
|
||||
}
|
||||
|
||||
export async function doWelcome(
|
||||
auth: string,
|
||||
issueNumber: number,
|
||||
body: string,
|
||||
labels?: string[] | void,
|
||||
assignees?: string[] | void,
|
||||
emoji?: string,
|
||||
) {
|
||||
core.info(`[doWelcome] [${auth}]`);
|
||||
const issues = await doQueryIssues('all', auth, true);
|
||||
if (issues.length == 0 || (issues.length == 1 && issues[0].number == issueNumber)) {
|
||||
if (body) {
|
||||
await doCreateComment(body, emoji);
|
||||
}
|
||||
|
||||
if (assignees?.length) {
|
||||
await doAddAssignees(assignees);
|
||||
}
|
||||
|
||||
if (labels?.length) {
|
||||
await doAddLabels(labels);
|
||||
}
|
||||
|
||||
const issueEmoji = core.getInput('issue-emoji');
|
||||
if (issueEmoji) {
|
||||
await ICE.createIssueEmoji(dealStringToArr(issueEmoji) as TEmoji[]);
|
||||
}
|
||||
} else {
|
||||
core.info(`[doWelcome] ${auth} is not first time!`);
|
||||
}
|
||||
}
|
176
src/helper/base.ts
Normal file
176
src/helper/base.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import { dealStringToArr } from 'actions-util';
|
||||
|
||||
import * as core from '../core';
|
||||
import type { IIssueCoreEngine } from '../issue';
|
||||
import { ELockReasons } from '../shared';
|
||||
import type { TCloseReason, TEmoji, TIssueState, TLockReasons, TUpdateMode } from '../types';
|
||||
|
||||
let ICE: IIssueCoreEngine;
|
||||
export function initBaseICE(_ICE: IIssueCoreEngine) {
|
||||
ICE = _ICE;
|
||||
}
|
||||
|
||||
export async function doAddAssignees(assignees: string[]) {
|
||||
await ICE.addAssignees(assignees);
|
||||
core.info(`[doAddAssignees] [${assignees}] success!`);
|
||||
}
|
||||
|
||||
export async function doAddLabels(labels: string[], issueNumber?: number) {
|
||||
if (issueNumber) ICE.setIssueNumber(issueNumber);
|
||||
await ICE.addLabels(labels);
|
||||
core.info(`[doAddLabels] [${labels}] success!`);
|
||||
}
|
||||
|
||||
export async function doCloseIssue(reason: TCloseReason, issueNumber?: number) {
|
||||
if (issueNumber) ICE.setIssueNumber(issueNumber);
|
||||
await ICE.closeIssue(reason);
|
||||
core.info(`[doCloseIssue] success!`);
|
||||
}
|
||||
|
||||
export async function doCreateComment(body: string, emoji?: string, issueNumber?: number) {
|
||||
if (body) {
|
||||
if (issueNumber) ICE.setIssueNumber(issueNumber);
|
||||
const commentId = await ICE.createComment(body);
|
||||
core.info(`[doCreateComment] [${body}] success!`);
|
||||
core.setOutput('comment-id', commentId);
|
||||
if (emoji) {
|
||||
await doCreateCommentEmoji(commentId, emoji);
|
||||
}
|
||||
} else {
|
||||
core.warning(`[doCreateComment] body is empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doCreateCommentEmoji(_commentId: number | void, emoji: string) {
|
||||
const commentId = _commentId || core.getInput('comment-id');
|
||||
if (emoji && commentId) {
|
||||
await ICE.createCommentEmoji(+commentId, dealStringToArr(emoji) as TEmoji[]);
|
||||
core.info(`[doCreateCommentEmoji] [${emoji}] success!`);
|
||||
} else {
|
||||
core.warning(`[doCreateCommentEmoji] emoji or commentId is empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doCreateIssue(
|
||||
title: string,
|
||||
body: string,
|
||||
labels?: string[],
|
||||
assignees?: string[],
|
||||
emoji?: string | void,
|
||||
) {
|
||||
if (title) {
|
||||
const issueNumber = await ICE.createIssue(title, body, labels, assignees);
|
||||
core.info(`[doCreateIssue] [${title}] success!`);
|
||||
core.setOutput('issue-number', issueNumber);
|
||||
if (emoji) {
|
||||
ICE.setIssueNumber(issueNumber);
|
||||
await ICE.createIssueEmoji(dealStringToArr(emoji) as TEmoji[]);
|
||||
core.info(`[createIssueEmoji] [${emoji}] success!`);
|
||||
}
|
||||
} else {
|
||||
core.warning(`[doCreateIssue] title is empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doCreateLabel() {
|
||||
const name = core.getInput('label-name');
|
||||
const color = core.getInput('label-color') || 'ededed';
|
||||
const description = core.getInput('label-desc') || '';
|
||||
|
||||
if (name) {
|
||||
await ICE.createLabel(name, color, description);
|
||||
core.info(`[doCreateLabel] [${name}] success!`);
|
||||
} else {
|
||||
core.warning(`[doCreateLabel] label-name is empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doDeleteComment(_commentId: number | void) {
|
||||
const commentId = _commentId || core.getInput('comment-id');
|
||||
if (commentId) {
|
||||
await ICE.deleteComment(+commentId);
|
||||
core.info(`[doDeleteComment] [${commentId}] success!`);
|
||||
} else {
|
||||
core.warning(`[doDeleteComment] commentId is empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doGetIssue() {
|
||||
const { number, title, body, state, labels, assignees } = await ICE.getIssue();
|
||||
core.setOutput('issue-number', number);
|
||||
core.setOutput('issue-title', title || '');
|
||||
core.setOutput('issue-body', body || '');
|
||||
core.setOutput('issue-state', state);
|
||||
const labelsString = labels.length ? labels.map(({ name }) => name).join(',') : '';
|
||||
core.setOutput('issue-labels', labelsString);
|
||||
const assigneesString = assignees.length ? assignees.map(({ login }) => login).join(',') : '';
|
||||
core.setOutput('issue-body', assigneesString);
|
||||
}
|
||||
|
||||
export async function doLockIssue(issueNumber?: number) {
|
||||
if (issueNumber) ICE.setIssueNumber(issueNumber);
|
||||
const lockReason = (core.getInput('lock-reason') || '') as TLockReasons;
|
||||
if (lockReason && !ELockReasons[lockReason]) {
|
||||
core.warning(`[doLockIssue] lock-reason is illegal!`);
|
||||
return;
|
||||
}
|
||||
await ICE.lockIssue(lockReason as TLockReasons);
|
||||
core.info(`[doLockIssue] success!`);
|
||||
}
|
||||
|
||||
export async function doOpenIssue() {
|
||||
await ICE.openIssue();
|
||||
core.info(`[doOpenIssue] success!`);
|
||||
}
|
||||
|
||||
export async function doRemoveAssignees(assignees: string[]) {
|
||||
await ICE.removeAssignees(assignees);
|
||||
core.info(`[doRemoveAssignees] [${assignees}] success!`);
|
||||
}
|
||||
|
||||
export async function doRemoveLabels(labels: string[]) {
|
||||
await ICE.removeLabels(labels);
|
||||
core.info(`[doRemoveLabels] [${labels}] success!`);
|
||||
}
|
||||
|
||||
export async function doSetLabels(labels: string[]) {
|
||||
await ICE.setLabels(labels);
|
||||
core.info(`[doSetLabels] [${labels}] success!`);
|
||||
}
|
||||
|
||||
export async function doUnlockIssue() {
|
||||
await ICE.unlockIssue();
|
||||
core.info(`[doUnlockIssue] success!`);
|
||||
}
|
||||
|
||||
export async function doUpdateComment(
|
||||
_commentId: number | void,
|
||||
body: string,
|
||||
updateMode: TUpdateMode,
|
||||
emoji: string | void,
|
||||
) {
|
||||
const commentId = _commentId || core.getInput('comment-id');
|
||||
if (commentId) {
|
||||
await ICE.updateComment(+commentId, body, updateMode);
|
||||
core.info(`[doUpdateComment] [${commentId}] success!`);
|
||||
if (emoji) {
|
||||
await doCreateCommentEmoji(+commentId, emoji);
|
||||
}
|
||||
} else {
|
||||
core.warning(`[doUpdateComment] commentId is empty!`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function doUpdateIssue(
|
||||
issueNumber: number,
|
||||
state: TIssueState,
|
||||
title: string | void,
|
||||
body: string | void,
|
||||
updateMode: TUpdateMode,
|
||||
labels?: string[] | void,
|
||||
assignees?: string[] | void,
|
||||
) {
|
||||
if (issueNumber) ICE.setIssueNumber(issueNumber);
|
||||
await ICE.updateIssue(state, title, body, updateMode, labels, assignees);
|
||||
core.info(`[doUpdateIssue] success!`);
|
||||
}
|
282
src/helper/helper.ts
Normal file
282
src/helper/helper.ts
Normal file
@@ -0,0 +1,282 @@
|
||||
import { dealStringToArr } from 'actions-util';
|
||||
|
||||
import * as core from '../core';
|
||||
import type { IIssueCoreEngine, TCommentInfo } from '../issue';
|
||||
import { IssueCoreEngine } from '../issue';
|
||||
import type { Context, TAction, TCloseReason, TIssueState, TUpdateMode } from '../types';
|
||||
import { dealRandomAssignees } from '../util';
|
||||
import {
|
||||
doCheckInactive,
|
||||
doCheckIssue,
|
||||
doCloseIssues,
|
||||
doFindComments,
|
||||
doFindIssues,
|
||||
doLockIssues,
|
||||
doMarkAssignees,
|
||||
doMarkDuplicate,
|
||||
doToggleLabels,
|
||||
doWelcome,
|
||||
initAdvancedICE,
|
||||
} from './advanced';
|
||||
import {
|
||||
doAddAssignees,
|
||||
doAddLabels,
|
||||
doCloseIssue,
|
||||
doCreateComment,
|
||||
doCreateIssue,
|
||||
doCreateLabel,
|
||||
doDeleteComment,
|
||||
doGetIssue,
|
||||
doLockIssue,
|
||||
doOpenIssue,
|
||||
doRemoveAssignees,
|
||||
doRemoveLabels,
|
||||
doSetLabels,
|
||||
doUnlockIssue,
|
||||
doUpdateComment,
|
||||
doUpdateIssue,
|
||||
initBaseICE,
|
||||
} from './base';
|
||||
import type { IIssueHelperEngine } from './types';
|
||||
|
||||
export class IssueHelperEngine implements IIssueHelperEngine {
|
||||
private ICE!: IIssueCoreEngine;
|
||||
|
||||
private owner!: string;
|
||||
private repo!: string;
|
||||
private issueNumber!: number;
|
||||
|
||||
private emoji?: string;
|
||||
private labels?: string[];
|
||||
private assignees?: string[];
|
||||
private title: string = '';
|
||||
private body: string = '';
|
||||
private state: TIssueState = 'open';
|
||||
private updateMode: TUpdateMode = 'replace';
|
||||
private closeReason: TCloseReason = 'not_planned';
|
||||
|
||||
public constructor(readonly ctx: Context) {
|
||||
this.initInput(ctx);
|
||||
this.initIssueCore();
|
||||
initBaseICE(this.ICE);
|
||||
initAdvancedICE(this.ICE);
|
||||
}
|
||||
|
||||
private initInput(ctx: Context) {
|
||||
// No display to outside
|
||||
const repoInput = core.getInput('repo');
|
||||
if (repoInput) {
|
||||
this.owner = repoInput.split('/')[0];
|
||||
this.repo = repoInput.split('/')[1];
|
||||
} else {
|
||||
this.owner = ctx.repo.owner;
|
||||
this.repo = ctx.repo.repo;
|
||||
}
|
||||
|
||||
let defaultCtxNumber: number | undefined;
|
||||
if (ctx.eventName === 'issues' || ctx.eventName === 'issue_comment') {
|
||||
defaultCtxNumber = ctx.payload.issue?.number;
|
||||
}
|
||||
const issueNumber = core.getInput('issue-number') || defaultCtxNumber;
|
||||
if (issueNumber) {
|
||||
this.issueNumber = +issueNumber;
|
||||
} else {
|
||||
core.warning(`'issue-number' is missing or this action not needed yet!`);
|
||||
}
|
||||
|
||||
this.emoji = core.getInput('emoji') || '';
|
||||
this.labels = dealStringToArr(core.getInput('labels') || '');
|
||||
|
||||
const assigneesInput = core.getInput('assignees') || '';
|
||||
const randomTo = core.getInput('random-to');
|
||||
this.assignees = dealRandomAssignees(assigneesInput, randomTo);
|
||||
|
||||
this.title = core.getInput('title') || '';
|
||||
this.body = core.getInput('body') || '';
|
||||
this.state = core.getInput('state') === 'closed' ? 'closed' : 'open';
|
||||
this.updateMode = core.getInput('update-mode') === 'append' ? 'append' : 'replace';
|
||||
this.closeReason = core.getInput('close-reason') === 'completed' ? 'completed' : 'not_planned';
|
||||
}
|
||||
|
||||
private initIssueCore() {
|
||||
const { owner, repo, issueNumber } = this;
|
||||
const token = core.getInput('token');
|
||||
this.ICE = new IssueCoreEngine({
|
||||
owner,
|
||||
repo,
|
||||
issueNumber,
|
||||
token,
|
||||
});
|
||||
core.info(`[Init] [${owner}/${repo} => ${issueNumber}]`);
|
||||
}
|
||||
|
||||
public async doExeAction(action: TAction) {
|
||||
const {
|
||||
issueNumber,
|
||||
emoji,
|
||||
labels,
|
||||
assignees,
|
||||
title,
|
||||
body,
|
||||
updateMode,
|
||||
state,
|
||||
ctx,
|
||||
closeReason,
|
||||
} = this;
|
||||
switch (action) {
|
||||
// ---[ Base Begin ]--->>>
|
||||
case 'add-assignees': {
|
||||
if (assignees && assignees.length) {
|
||||
await doAddAssignees(assignees);
|
||||
} else {
|
||||
core.warning(`[doAddAssignees] assignees is empty!`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'add-labels': {
|
||||
if (labels && labels.length) {
|
||||
await doAddLabels(labels);
|
||||
} else {
|
||||
core.warning(`[doAddLabels] labels is empty!`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'close-issue': {
|
||||
await doCloseIssue(closeReason);
|
||||
break;
|
||||
}
|
||||
case 'create-comment': {
|
||||
await doCreateComment(body, emoji);
|
||||
break;
|
||||
}
|
||||
case 'create-issue': {
|
||||
await doCreateIssue(title, body, labels, assignees, emoji);
|
||||
break;
|
||||
}
|
||||
case 'create-label': {
|
||||
await doCreateLabel();
|
||||
break;
|
||||
}
|
||||
case 'delete-comment': {
|
||||
await doDeleteComment();
|
||||
break;
|
||||
}
|
||||
case 'get-issue': {
|
||||
await doGetIssue();
|
||||
break;
|
||||
}
|
||||
case 'lock-issue': {
|
||||
await doLockIssue();
|
||||
break;
|
||||
}
|
||||
case 'open-issue': {
|
||||
await doOpenIssue();
|
||||
break;
|
||||
}
|
||||
case 'remove-assignees': {
|
||||
if (assignees && assignees.length) {
|
||||
await doRemoveAssignees(assignees);
|
||||
} else {
|
||||
core.warning(`[doRemoveAssignees] assignees is empty!`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'remove-labels': {
|
||||
if (labels && labels.length) {
|
||||
await doRemoveLabels(labels);
|
||||
} else {
|
||||
core.warning(`[doRemoveLabels] labels is empty!`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'set-labels': {
|
||||
if (labels && labels.length) {
|
||||
await doSetLabels(labels);
|
||||
} else {
|
||||
core.warning(`[doSetLabels] labels is empty!`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'unlock-issue': {
|
||||
await doUnlockIssue();
|
||||
break;
|
||||
}
|
||||
case 'update-comment': {
|
||||
await doUpdateComment(0, body, updateMode, emoji);
|
||||
break;
|
||||
}
|
||||
case 'update-issue': {
|
||||
await doUpdateIssue(0, state, title, body, updateMode, labels, assignees);
|
||||
break;
|
||||
}
|
||||
// ---[ Base End ]--->>>
|
||||
// ^_^ ============= ^_^
|
||||
// -[ Advanced Begin ]->
|
||||
case 'check-inactive': {
|
||||
await doCheckInactive(body, emoji);
|
||||
break;
|
||||
}
|
||||
case 'check-issue': {
|
||||
await doCheckIssue();
|
||||
break;
|
||||
}
|
||||
case 'close-issues': {
|
||||
await doCloseIssues(body, closeReason, emoji);
|
||||
break;
|
||||
}
|
||||
case 'find-comments': {
|
||||
await doFindComments();
|
||||
break;
|
||||
}
|
||||
case 'find-issues': {
|
||||
await doFindIssues();
|
||||
break;
|
||||
}
|
||||
case 'lock-issues': {
|
||||
await doLockIssues(body, emoji);
|
||||
break;
|
||||
}
|
||||
case 'mark-assignees': {
|
||||
if (this.checkEvent4Mark()) {
|
||||
core.warning(`[mark-assignees] only support event '[issue_comment: created/edited]'!`);
|
||||
return;
|
||||
}
|
||||
await doMarkAssignees(ctx.payload.comment as TCommentInfo);
|
||||
break;
|
||||
}
|
||||
case 'mark-duplicate': {
|
||||
if (this.checkEvent4Mark()) {
|
||||
core.warning(`[mark-duplicate] only support event '[issue_comment: created/edited]'!`);
|
||||
return;
|
||||
}
|
||||
await doMarkDuplicate(ctx.payload.comment as TCommentInfo, closeReason, labels, emoji);
|
||||
break;
|
||||
}
|
||||
case 'toggle-labels': {
|
||||
await doToggleLabels(labels);
|
||||
break;
|
||||
}
|
||||
case 'welcome': {
|
||||
if (ctx.eventName === 'issues' && ctx.payload.action === 'opened') {
|
||||
await doWelcome(ctx.actor, issueNumber, body, labels, assignees, emoji);
|
||||
} else {
|
||||
core.warning('[welcome] only support issue opened!');
|
||||
}
|
||||
break;
|
||||
}
|
||||
// -[ Advanced End ]->
|
||||
default: {
|
||||
core.warning(`The ${action} is not allowed.`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private checkEvent4Mark() {
|
||||
const { ctx } = this;
|
||||
return (
|
||||
ctx.eventName !== 'issue_comment' &&
|
||||
(ctx.payload.action === 'created' || ctx.payload.action === 'edited')
|
||||
);
|
||||
}
|
||||
}
|
2
src/helper/index.ts
Normal file
2
src/helper/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './helper';
|
||||
export * from './types';
|
5
src/helper/types.ts
Normal file
5
src/helper/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { TAction } from '../types';
|
||||
|
||||
export interface IIssueHelperEngine {
|
||||
doExeAction: (action: TAction) => Promise<void>;
|
||||
}
|
2
src/issue/index.ts
Normal file
2
src/issue/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './issue';
|
||||
export * from './types';
|
337
src/issue/issue.ts
Normal file
337
src/issue/issue.ts
Normal file
@@ -0,0 +1,337 @@
|
||||
import { Octokit } from '@octokit/rest';
|
||||
|
||||
import { EEmoji } from '../shared';
|
||||
import type {
|
||||
TCloseReason,
|
||||
TEmoji,
|
||||
TIssueState,
|
||||
TLockReasons,
|
||||
TUpdateMode,
|
||||
TUserPermission,
|
||||
} from '../types';
|
||||
import type {
|
||||
IIssueBaseInfo,
|
||||
IIssueCoreEngine,
|
||||
IListIssuesParams,
|
||||
TCommentList,
|
||||
TIssueInfo,
|
||||
TIssueList,
|
||||
} from './types';
|
||||
|
||||
export class IssueCoreEngine implements IIssueCoreEngine {
|
||||
private owner!: string;
|
||||
private repo!: string;
|
||||
private issueNumber!: number;
|
||||
private octokit!: Octokit;
|
||||
|
||||
public constructor(_info: IIssueBaseInfo) {
|
||||
if (_info.owner && _info.repo) {
|
||||
this.owner = _info.owner;
|
||||
this.repo = _info.repo;
|
||||
this.issueNumber = _info.issueNumber;
|
||||
this.octokit = new Octokit({ auth: `token ${_info.token}` });
|
||||
} else {
|
||||
console.error(`Init failed, need owner、repo!`);
|
||||
}
|
||||
}
|
||||
|
||||
// Allow modify issue number in this way
|
||||
public setIssueNumber(newIssueNumber: number) {
|
||||
this.issueNumber = newIssueNumber;
|
||||
}
|
||||
|
||||
public async addAssignees(assignees: string[]) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
await octokit.issues.addAssignees({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
assignees,
|
||||
});
|
||||
}
|
||||
|
||||
public async addLabels(labels: string[]) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
await octokit.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
labels,
|
||||
});
|
||||
}
|
||||
|
||||
public async closeIssue(reason: TCloseReason) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
await octokit.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
state: 'closed',
|
||||
state_reason: reason,
|
||||
});
|
||||
}
|
||||
|
||||
public async createComment(body: string): Promise<number> {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
const { data } = await octokit.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
body,
|
||||
});
|
||||
return data.id;
|
||||
}
|
||||
|
||||
public async createCommentEmoji(commentId: number, emoji: TEmoji[]) {
|
||||
const { owner, repo, octokit } = this;
|
||||
for (const content of emoji) {
|
||||
if (content && EEmoji[content]) {
|
||||
await octokit.reactions.createForIssueComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId,
|
||||
content,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async createIssue(
|
||||
title: string,
|
||||
body: string,
|
||||
labels?: string[],
|
||||
assignees?: string[],
|
||||
): Promise<number> {
|
||||
const { owner, repo, octokit } = this;
|
||||
const { data } = await octokit.issues.create({
|
||||
owner,
|
||||
repo,
|
||||
title,
|
||||
body,
|
||||
labels,
|
||||
assignees,
|
||||
});
|
||||
return data.number;
|
||||
}
|
||||
|
||||
public async createIssueEmoji(emoji: TEmoji[]) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
for (const content of emoji) {
|
||||
if (content && EEmoji[content]) {
|
||||
await octokit.reactions.createForIssue({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
content,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async createLabel(
|
||||
labelName: string,
|
||||
labelColor: string,
|
||||
labelDescription: string | undefined,
|
||||
) {
|
||||
const { owner, repo, octokit } = this;
|
||||
await octokit.issues.createLabel({
|
||||
owner,
|
||||
repo,
|
||||
name: labelName,
|
||||
color: labelColor,
|
||||
description: labelDescription,
|
||||
});
|
||||
}
|
||||
|
||||
public async deleteComment(commentId: number) {
|
||||
const { owner, repo, octokit } = this;
|
||||
await octokit.issues.deleteComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId,
|
||||
});
|
||||
}
|
||||
|
||||
public async getIssue() {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
const issue = await octokit.issues.get({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
return issue.data as unknown as TIssueInfo;
|
||||
}
|
||||
|
||||
public async getUserPermission(username: string) {
|
||||
const { owner, repo, octokit } = this;
|
||||
const { data } = await octokit.repos.getCollaboratorPermissionLevel({
|
||||
owner,
|
||||
repo,
|
||||
username,
|
||||
});
|
||||
return data.permission as TUserPermission;
|
||||
}
|
||||
|
||||
public async listComments(page = 1) {
|
||||
const { octokit, owner, repo, issueNumber } = this;
|
||||
const { data } = await octokit.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
per_page: 100,
|
||||
page,
|
||||
});
|
||||
let comments = [...data] as unknown as TCommentList;
|
||||
if (comments.length >= 100) {
|
||||
comments = comments.concat(await this.listComments(page + 1));
|
||||
}
|
||||
return comments;
|
||||
}
|
||||
|
||||
public async listIssues(params: IListIssuesParams, page = 1) {
|
||||
const { octokit, owner, repo } = this;
|
||||
const { data } = await octokit.issues.listForRepo({
|
||||
...params,
|
||||
owner,
|
||||
repo,
|
||||
per_page: 100,
|
||||
page,
|
||||
});
|
||||
let issues = [...data] as unknown as TIssueList;
|
||||
if (issues.length >= 100) {
|
||||
issues = issues.concat(await this.listIssues(params, page + 1));
|
||||
}
|
||||
return issues;
|
||||
}
|
||||
|
||||
public async lockIssue(lockReason: TLockReasons) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
const params: any = {
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
};
|
||||
if (lockReason) {
|
||||
params.lock_reason = lockReason;
|
||||
}
|
||||
await octokit.issues.lock(params);
|
||||
}
|
||||
|
||||
public async openIssue() {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
await octokit.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
state: 'open',
|
||||
});
|
||||
}
|
||||
|
||||
public async removeAssignees(assignees: string[]) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
await octokit.issues.removeAssignees({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
assignees,
|
||||
});
|
||||
}
|
||||
|
||||
public async removeLabels(labels: string[]) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
const issue = await this.getIssue();
|
||||
|
||||
const baseLabels: string[] = issue.labels.map(({ name }) => name);
|
||||
const removeLabels = baseLabels.filter(name => labels.includes(name));
|
||||
|
||||
for (const label of removeLabels) {
|
||||
await octokit.issues.removeLabel({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
name: label,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async setLabels(labels: string[]) {
|
||||
// https://github.com/octokit/rest.js/issues/34
|
||||
// - Probability to appear
|
||||
// - avoid use setLabels
|
||||
const issue = await this.getIssue();
|
||||
|
||||
const baseLabels: string[] = issue.labels.map(({ name }: any) => name);
|
||||
const removeLabels = baseLabels.filter(name => !labels.includes(name));
|
||||
const addLabels = labels.filter(name => !baseLabels.includes(name));
|
||||
|
||||
if (removeLabels.length) {
|
||||
await this.removeLabels(removeLabels);
|
||||
}
|
||||
|
||||
if (addLabels.length) {
|
||||
await this.addLabels(addLabels);
|
||||
}
|
||||
}
|
||||
|
||||
public async unlockIssue() {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
await octokit.issues.unlock({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
}
|
||||
|
||||
public async updateComment(commentId: number, body: string, mode: TUpdateMode) {
|
||||
const { owner, repo, octokit } = this;
|
||||
const comment = await octokit.issues.getComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId,
|
||||
});
|
||||
const baseBody = comment.data.body;
|
||||
const newBody = body ? (mode === 'append' ? `${baseBody}\n${body}` : body) : baseBody;
|
||||
|
||||
await octokit.issues.updateComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: commentId,
|
||||
body: newBody || '',
|
||||
});
|
||||
}
|
||||
|
||||
public async updateIssue(
|
||||
state: TIssueState,
|
||||
title: string | void,
|
||||
body: string | void,
|
||||
mode: TUpdateMode,
|
||||
labels?: string[] | void,
|
||||
assignees?: string[] | void,
|
||||
) {
|
||||
const { owner, repo, octokit, issueNumber } = this;
|
||||
const issue = await this.getIssue();
|
||||
const {
|
||||
body: baseBody,
|
||||
title: baseTitle,
|
||||
labels: baseLabels,
|
||||
assignees: baseAssigness,
|
||||
state: baseState,
|
||||
} = issue;
|
||||
|
||||
const baseLabelsName = baseLabels.map(({ name }: any) => name);
|
||||
const baseAssignessName = baseAssigness?.map(({ login }: any) => login);
|
||||
|
||||
const newBody = body ? (mode === 'append' ? `${baseBody}\n${body}` : body) : baseBody;
|
||||
|
||||
await octokit.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issueNumber,
|
||||
state: state || baseState,
|
||||
title: title || baseTitle,
|
||||
body: newBody,
|
||||
labels: labels?.length ? labels : baseLabelsName,
|
||||
assignees: assignees?.length ? assignees : baseAssignessName,
|
||||
});
|
||||
}
|
||||
}
|
117
src/issue/types.ts
Normal file
117
src/issue/types.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import type {
|
||||
TCloseReason,
|
||||
TEmoji,
|
||||
TIssueState,
|
||||
TLockReasons,
|
||||
TUpdateMode,
|
||||
TUserPermission,
|
||||
} from '../types';
|
||||
|
||||
export interface IIssueBaseInfo {
|
||||
owner: string;
|
||||
repo: string;
|
||||
issueNumber: number;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface IListIssuesParams {
|
||||
state: TIssueState | 'all';
|
||||
creator?: string;
|
||||
assignee?: string;
|
||||
mentioned?: string;
|
||||
labels?: string;
|
||||
}
|
||||
|
||||
export type TIssueInfo = {
|
||||
number: number;
|
||||
title: string;
|
||||
body: string;
|
||||
user: {
|
||||
login: string;
|
||||
};
|
||||
assignees: {
|
||||
login: string;
|
||||
}[];
|
||||
labels: {
|
||||
name: string;
|
||||
}[];
|
||||
state: TIssueState;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
pull_request?: any;
|
||||
};
|
||||
|
||||
export type TIssueList = TIssueInfo[];
|
||||
|
||||
export type TCommentInfo = {
|
||||
id: number;
|
||||
body: string;
|
||||
user: {
|
||||
login: string;
|
||||
};
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type TCommentList = TCommentInfo[];
|
||||
|
||||
export interface IIssueCoreEngine {
|
||||
setIssueNumber: (newIssueNumber: number) => void;
|
||||
addAssignees: (assignees: string[]) => Promise<void>;
|
||||
addLabels: (labels: string[]) => Promise<void>;
|
||||
|
||||
closeIssue: (reason: TCloseReason) => Promise<void>;
|
||||
/**
|
||||
* @param body The comment body.
|
||||
* @returns The create new comment id.
|
||||
*/
|
||||
createComment: (body: string) => Promise<number>;
|
||||
createCommentEmoji: (commentId: number, emoji: TEmoji[]) => Promise<void>;
|
||||
/**
|
||||
* @param title
|
||||
* @param body
|
||||
* @param labels
|
||||
* @param assignees
|
||||
* @returns The create new issue number.
|
||||
*/
|
||||
createIssue: (
|
||||
title: string,
|
||||
body: string,
|
||||
labels?: string[],
|
||||
assignees?: string[],
|
||||
) => Promise<number>;
|
||||
createIssueEmoji: (emoji: TEmoji[]) => Promise<void>;
|
||||
createLabel: (
|
||||
labelName: string,
|
||||
labelColor: string,
|
||||
labelDescription: string | undefined,
|
||||
) => Promise<void>;
|
||||
|
||||
deleteComment: (commentId: number) => Promise<void>;
|
||||
|
||||
getIssue: () => Promise<TIssueInfo>;
|
||||
getUserPermission: (username: string) => Promise<TUserPermission>;
|
||||
|
||||
listComments: () => Promise<TCommentList>;
|
||||
listIssues: (params: IListIssuesParams) => Promise<TIssueList>;
|
||||
lockIssue: (lockReason: TLockReasons) => Promise<void>;
|
||||
|
||||
openIssue: () => Promise<void>;
|
||||
|
||||
removeAssignees: (assignees: string[]) => Promise<void>;
|
||||
removeLabels: (labels: string[]) => Promise<void>;
|
||||
|
||||
setLabels: (labels: string[]) => Promise<void>;
|
||||
|
||||
unlockIssue: () => Promise<void>;
|
||||
|
||||
updateComment: (commentId: number, body: string, mode: TUpdateMode) => Promise<void>;
|
||||
updateIssue: (
|
||||
state: TIssueState,
|
||||
title: string | void,
|
||||
body: string | void,
|
||||
mode: TUpdateMode,
|
||||
labels?: string[] | void,
|
||||
assignees?: string[] | void,
|
||||
) => Promise<void>;
|
||||
}
|
214
src/main.js
214
src/main.js
@@ -1,214 +0,0 @@
|
||||
const core = require("@actions/core");
|
||||
const github = require("@actions/github");
|
||||
|
||||
const {
|
||||
doAddAssignees,
|
||||
doAddLabels,
|
||||
doCloseIssue,
|
||||
doCreateComment,
|
||||
doCreateCommentContent,
|
||||
doCreateIssue,
|
||||
doCreateIssueContent,
|
||||
doDeleteComment,
|
||||
doLockIssue,
|
||||
doOpenIssue,
|
||||
doRemoveAssignees,
|
||||
doRemoveLabels,
|
||||
doSetLabels,
|
||||
doUnlockIssue,
|
||||
doUpdateComment,
|
||||
doUpdateIssue,
|
||||
doWelcome,
|
||||
} = require('./base.js');
|
||||
|
||||
const {
|
||||
doCheckInactive,
|
||||
doCheckIssue,
|
||||
doCloseIssues,
|
||||
doFindComments,
|
||||
doLockIssues,
|
||||
} = require('./advanced.js');
|
||||
|
||||
const ALLACTIONS = [
|
||||
// base
|
||||
'add-assignees',
|
||||
'add-labels',
|
||||
'close-issue',
|
||||
'create-comment',
|
||||
'create-issue',
|
||||
'delete-comment',
|
||||
'lock-issue',
|
||||
'open-issue',
|
||||
'remove-assignees',
|
||||
'remove-labels',
|
||||
'set-labels',
|
||||
'unlock-issue',
|
||||
'update-comment',
|
||||
'update-issue',
|
||||
'welcome',
|
||||
|
||||
// advanced
|
||||
'check-inactive',
|
||||
'check-issue',
|
||||
'close-issues',
|
||||
'find-comments',
|
||||
'lock-issues',
|
||||
];
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const owner = github.context.repo.owner;
|
||||
const repo = github.context.repo.repo;
|
||||
|
||||
const issueNumber = core.getInput('issue-number');
|
||||
const commentId = core.getInput('comment-id');
|
||||
|
||||
const defaultBody = `Currently at ${owner}/${repo}. And this is default comment.`
|
||||
const body = core.getInput("body") || defaultBody;
|
||||
|
||||
const defaultTitle = `Default Title`;
|
||||
const title = core.getInput("title") || defaultTitle;
|
||||
|
||||
const assignees = core.getInput("assignees");
|
||||
|
||||
const labels = core.getInput("labels");
|
||||
const state = core.getInput("state") || 'open';
|
||||
|
||||
let updateMode = core.getInput("update-mode");
|
||||
if (updateMode !== 'append') {
|
||||
updateMode = 'replace';
|
||||
}
|
||||
|
||||
const actions = core.getInput("actions", { required: true });
|
||||
const actionsArr = actions.split(',');
|
||||
actionsArr.forEach(item => {
|
||||
testActions(item.trim());
|
||||
});
|
||||
|
||||
function testActions(action) {
|
||||
if (ALLACTIONS.includes(action)) {
|
||||
choseActions(action);
|
||||
} else {
|
||||
core.setFailed("This actions not supported!");
|
||||
}
|
||||
};
|
||||
|
||||
async function choseActions(action) {
|
||||
switch (action) {
|
||||
// base
|
||||
case 'add-assignees':
|
||||
await doAddAssignees(owner, repo, issueNumber, assignees);
|
||||
break;
|
||||
case 'add-labels':
|
||||
await doAddLabels(owner, repo, issueNumber, labels);
|
||||
break;
|
||||
case 'close-issue':
|
||||
await doCloseIssue(owner, repo, issueNumber);
|
||||
break;
|
||||
case 'create-comment':
|
||||
await doCreateComment(owner, repo, issueNumber, body);
|
||||
break;
|
||||
case 'create-issue':
|
||||
await doCreateIssue(owner, repo, title, body, labels, assignees);
|
||||
break;
|
||||
case 'delete-comment':
|
||||
await doDeleteComment(owner, repo, commentId);
|
||||
break;
|
||||
case 'lock-issue':
|
||||
await doLockIssue(owner, repo, issueNumber);
|
||||
break;
|
||||
case 'open-issue':
|
||||
await doOpenIssue(owner, repo, issueNumber);
|
||||
break;
|
||||
case 'remove-assignees':
|
||||
await doRemoveAssignees(owner, repo, issueNumber, assignees);
|
||||
break;
|
||||
case 'remove-labels':
|
||||
await doRemoveLabels(owner, repo, issueNumber, labels);
|
||||
break;
|
||||
case 'set-labels':
|
||||
await doSetLabels(owner, repo, issueNumber, labels);
|
||||
break;
|
||||
case 'unlock-issue':
|
||||
await doUnlockIssue(owner, repo, issueNumber);
|
||||
break;
|
||||
case 'update-comment':
|
||||
await doUpdateComment(
|
||||
owner,
|
||||
repo,
|
||||
commentId,
|
||||
body,
|
||||
updateMode
|
||||
);
|
||||
break;
|
||||
case 'update-issue':
|
||||
await doUpdateIssue(
|
||||
owner,
|
||||
repo,
|
||||
issueNumber,
|
||||
state,
|
||||
title,
|
||||
body,
|
||||
updateMode,
|
||||
assignees,
|
||||
labels
|
||||
);
|
||||
break;
|
||||
case 'welcome':
|
||||
await doWelcome(
|
||||
owner,
|
||||
repo,
|
||||
assignees,
|
||||
labels,
|
||||
body
|
||||
);
|
||||
break;
|
||||
|
||||
// advanced
|
||||
case 'check-inactive':
|
||||
await doCheckInactive(
|
||||
owner,
|
||||
repo,
|
||||
labels
|
||||
)
|
||||
break;
|
||||
case 'check-issue':
|
||||
await doCheckIssue(
|
||||
owner,
|
||||
repo,
|
||||
issueNumber
|
||||
);
|
||||
break;
|
||||
case 'close-issues':
|
||||
await doCloseIssues(
|
||||
owner,
|
||||
repo,
|
||||
labels
|
||||
)
|
||||
break;
|
||||
case 'find-comments':
|
||||
await doFindComments(
|
||||
owner,
|
||||
repo,
|
||||
issueNumber
|
||||
);
|
||||
break;
|
||||
case 'lock-issues':
|
||||
await doLockIssues(
|
||||
owner,
|
||||
repo,
|
||||
labels
|
||||
);
|
||||
break;
|
||||
// default
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
21
src/main.ts
Normal file
21
src/main.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as github from '@actions/github';
|
||||
import { dealStringToArr, THANKS } from 'actions-util';
|
||||
|
||||
import * as core from './core';
|
||||
import { IssueHelperEngine } from './helper';
|
||||
import type { TAction } from './types';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const actions = core.getInput('actions', { required: true });
|
||||
const IHE = new IssueHelperEngine(github.context);
|
||||
for (const action of dealStringToArr(actions)) {
|
||||
await IHE.doExeAction(action as TAction);
|
||||
}
|
||||
core.baseInfo(`\n${THANKS}`);
|
||||
} catch (err: any) {
|
||||
core.setFailed(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
21
src/shared.ts
Normal file
21
src/shared.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export const EEmoji = {
|
||||
'+1': '+1',
|
||||
'-1': '-1',
|
||||
laugh: 'laugh',
|
||||
confused: 'confused',
|
||||
heart: 'heart',
|
||||
hooray: 'hooray',
|
||||
rocket: 'rocket',
|
||||
eyes: 'eyes',
|
||||
};
|
||||
|
||||
export const ELockReasons = {
|
||||
'off-topic': 'off-topic',
|
||||
'too heated': 'too heated',
|
||||
resolved: 'resolved',
|
||||
spam: 'spam',
|
||||
};
|
||||
|
||||
export const EConst = {
|
||||
ExcludeEmpty: '$exclude-empty',
|
||||
};
|
61
src/types.ts
Normal file
61
src/types.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { TPermissionType } from 'actions-util';
|
||||
|
||||
export { Context } from '@actions/github/lib/context';
|
||||
|
||||
export type TEmoji = '+1' | '-1' | 'laugh' | 'confused' | 'heart' | 'hooray' | 'rocket' | 'eyes';
|
||||
|
||||
export type TLockReasons = 'off-topic' | 'too heated' | 'resolved' | 'spam' | undefined;
|
||||
|
||||
export type TIssueState = 'open' | 'closed';
|
||||
|
||||
export type TUpdateMode = 'append' | 'replace';
|
||||
|
||||
export type TUserPermission = TPermissionType;
|
||||
|
||||
export type TCloseReason = 'completed' | 'not_planned';
|
||||
|
||||
export type TOutInfo = {
|
||||
auth: string;
|
||||
id?: number;
|
||||
number?: number;
|
||||
title?: string;
|
||||
body?: string;
|
||||
state?: TIssueState;
|
||||
created: string;
|
||||
updated: string;
|
||||
};
|
||||
|
||||
export type TOutList = TOutInfo[];
|
||||
|
||||
export type TAction =
|
||||
// [ Base Begin ]
|
||||
| 'add-assignees'
|
||||
| 'add-labels'
|
||||
| 'close-issue'
|
||||
| 'create-comment'
|
||||
| 'create-issue'
|
||||
| 'create-label'
|
||||
| 'delete-comment'
|
||||
| 'lock-issue'
|
||||
| 'open-issue'
|
||||
| 'remove-assignees'
|
||||
| 'remove-labels'
|
||||
| 'set-labels'
|
||||
| 'unlock-issue'
|
||||
| 'update-comment'
|
||||
| 'update-issue'
|
||||
// [ Base End ]
|
||||
// ^_^ ========== ^_^
|
||||
// [ Advanced Begin ]
|
||||
| 'check-inactive'
|
||||
| 'check-issue'
|
||||
| 'close-issues'
|
||||
| 'find-comments'
|
||||
| 'find-issues'
|
||||
| 'get-issue'
|
||||
| 'lock-issues'
|
||||
| 'mark-assignees'
|
||||
| 'mark-duplicate'
|
||||
| 'toggle-labels'
|
||||
| 'welcome';
|
||||
//// [ Advanced End ]
|
21
src/util.js
21
src/util.js
@@ -1,21 +0,0 @@
|
||||
function dealInput (para) {
|
||||
let arr = [];
|
||||
if (para) {
|
||||
const paraArr = para.split(',');
|
||||
paraArr.forEach(it => {
|
||||
if(it.trim()){
|
||||
arr.push(it.trim())
|
||||
}
|
||||
})
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
function matchKeyword(content, keywords) {
|
||||
return keywords.find(item => content.toLowerCase().includes(item));
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
dealInput,
|
||||
matchKeyword,
|
||||
};
|
35
src/util/index.ts
Normal file
35
src/util/index.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { dealStringToArr } from 'actions-util';
|
||||
import sampleSize from 'lodash/sampleSize';
|
||||
|
||||
export const dealRandomAssignees = (assignees: string, randomTo: string | void): string[] => {
|
||||
let arr = dealStringToArr(assignees);
|
||||
if (randomTo && Number(randomTo) > 0 && Number(randomTo) < arr.length) {
|
||||
arr = sampleSize(arr, Number(randomTo));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
export const matchKeyword = (content: string = '', keywords: string[]): boolean => {
|
||||
return !!keywords.find(item => content?.toLowerCase().includes(item));
|
||||
};
|
||||
|
||||
export const checkDuplicate = (body: string | void): boolean => {
|
||||
if (!body || !body.startsWith('Duplicate of')) {
|
||||
return false;
|
||||
}
|
||||
const arr = body.split(' ');
|
||||
return arr[0] == 'Duplicate' && arr[1] == 'of';
|
||||
};
|
||||
|
||||
export const getPreMonth = (m: number): number => {
|
||||
return m == 1 ? 12 : m - 1;
|
||||
};
|
||||
|
||||
// replace some & split & cull empty
|
||||
export const replaceStr2Arr = (str: string, replace: string, split: string): string[] => {
|
||||
return str
|
||||
.replace(replace, '')
|
||||
.trim()
|
||||
.split(split)
|
||||
.reduce((result: string[], it) => (it ? [...result, it.trim()] : result), []);
|
||||
};
|
55
tests/index.test.ts
Normal file
55
tests/index.test.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { replaceStr2Arr } from '../src/util';
|
||||
|
||||
describe('Test', () => {
|
||||
it('test doQueryIssues', () => {
|
||||
const issues = [
|
||||
{
|
||||
id: 0,
|
||||
labels: [{ name: '0' }, { name: '1' }],
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
labels: [{ name: '1' }, { name: '2' }],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
labels: [{ name: '2' }, { name: '3' }],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
labels: [{ name: '1' }, { name: '4' }],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
labels: [{ name: '1' }, { name: '3' }],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
labels: [{ name: '1' }, { name: '5' }],
|
||||
},
|
||||
];
|
||||
|
||||
let ex = ['2', '4'];
|
||||
let r = [];
|
||||
|
||||
issues.forEach(iss => {
|
||||
for (let i = 0; i < iss.labels.length; i += 1) {
|
||||
if (ex.includes(iss.labels[i].name)) return;
|
||||
}
|
||||
r.push(iss);
|
||||
});
|
||||
|
||||
expect(r[0].id).toEqual(0);
|
||||
expect(r[1].id).toEqual(4);
|
||||
expect(r[2].id).toEqual(5);
|
||||
expect(r.length).toEqual(3);
|
||||
});
|
||||
|
||||
it('test replaceStr2Arr', () => {
|
||||
const st = '/assign @1 @2 @3@a 3 @s @1_2 2';
|
||||
const re = '/assign';
|
||||
const sp = '@';
|
||||
|
||||
expect(replaceStr2Arr(st, re, sp)).toEqual(['1', '2', '3', 'a 3', 's', '1_2 2']);
|
||||
});
|
||||
});
|
@@ -1,16 +1,77 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"baseUrl": "./",
|
||||
"jsx": "preserve",
|
||||
"declaration": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@@/*": ["src/.umi/*"],
|
||||
"rc-dialog": ["src/index.ts"]
|
||||
}
|
||||
}
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6",
|
||||
/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs",
|
||||
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./lib",
|
||||
/* Redirect output structure to the directory. */
|
||||
"rootDir": "./src",
|
||||
/* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true,
|
||||
/* Enable all strict type-checking options. */
|
||||
"noImplicitAny": true,
|
||||
/* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true
|
||||
/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"lib",
|
||||
"dist",
|
||||
"docs-dist",
|
||||
"web",
|
||||
"**/*.test.ts"
|
||||
]
|
||||
}
|
||||
|
61
web/.dumi/global.less
Normal file
61
web/.dumi/global.less
Normal file
File diff suppressed because one or more lines are too long
47
web/.dumirc.ts
Normal file
47
web/.dumirc.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
// more config: https://d.umijs.org/config
|
||||
import { defineConfig } from 'dumi';
|
||||
import path from 'path';
|
||||
import remarkPlugin from './remark-plugins';
|
||||
|
||||
const name = 'issues-helper';
|
||||
|
||||
const isProdSite =
|
||||
// 不是预览模式 同时是生产环境
|
||||
process.env.PREVIEW !== 'true' && process.env.NODE_ENV === 'production';
|
||||
|
||||
const logo =
|
||||
'https://gw.alipayobjects.com/mdn/rms_f97235/afts/img/A*8xDgSL-O6O4AAAAAAAAAAAAAARQnAQ';
|
||||
|
||||
export default defineConfig({
|
||||
title: 'Issues Helper',
|
||||
outputPath: '../docs-dist',
|
||||
base: isProdSite ? `/${name}/` : '/',
|
||||
publicPath: isProdSite ? `/${name}/` : '/',
|
||||
locales: [
|
||||
{ id: 'en-US', name: 'English', },
|
||||
{ id: 'zh-CN', name: '中文' },
|
||||
],
|
||||
favicons: [logo],
|
||||
extraRemarkPlugins: [remarkPlugin],
|
||||
themeConfig: {
|
||||
logo,
|
||||
nav: {
|
||||
'zh-CN': [
|
||||
{ title: '指 南', link: '/zh-CN/guide' },
|
||||
{ title: '基 础', link: '/zh-CN/base' },
|
||||
{ title: '进 阶', link: '/zh-CN/advanced' },
|
||||
{ title: '更新日志', link: '/zh-CN/changelog' }
|
||||
],
|
||||
'en-US': [
|
||||
{ title: 'Guide', link: '/guide' },
|
||||
{ title: 'Base', link: '/base' },
|
||||
{ title: 'Advanced', link: '/advanced' },
|
||||
{ title: 'Changelog', link: '/changelog' },
|
||||
],
|
||||
},
|
||||
socialLinks: {
|
||||
github: 'https://github.com/actions-cool/issues-helper'
|
||||
},
|
||||
footer: 'Open-source MIT Licensed | Copyright © 2020-present<br />Powered by xrkffgg'
|
||||
},
|
||||
});
|
5
web/docs/advanced.md
Normal file
5
web/docs/advanced.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: 🌟 Advanced
|
||||
---
|
||||
|
||||
<embed src="../../README.md#RE-/<wrapper advanced [^>]*>([\s\S]*?)<\/wrapper>/"></embed>
|
5
web/docs/advanced.zh-CN.md
Normal file
5
web/docs/advanced.zh-CN.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: 🌟 进 阶
|
||||
---
|
||||
|
||||
<embed src="../../README.zh-CN.md#RE-/<wrapper advanced [^>]*>([\s\S]*?)<\/wrapper>/"></embed>
|
5
web/docs/base.md
Normal file
5
web/docs/base.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: ⭐ Base
|
||||
---
|
||||
|
||||
<embed src="../../README.md#RE-/<wrapper base [^>]*>([\s\S]*?)<\/wrapper>/"></embed>
|
5
web/docs/base.zh-CN.md
Normal file
5
web/docs/base.zh-CN.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: ⭐ 基 础
|
||||
---
|
||||
|
||||
<embed src="../../README.zh-CN.md#RE-/<wrapper base [^>]*>([\s\S]*?)<\/wrapper>/"></embed>
|
10
web/docs/changelog.md
Normal file
10
web/docs/changelog.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
# ✨ Changelog
|
||||
|
||||
- v2 [upgrade reference](/guide/faq)
|
||||
- v3 [changelog](/guide/faq#v3-changelog)
|
||||
|
||||
<embed src="../../CHANGELOG.md"></embed>
|
10
web/docs/changelog.zh-CN.md
Normal file
10
web/docs/changelog.zh-CN.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
toc: menu
|
||||
---
|
||||
|
||||
# ✨ 更新日志
|
||||
|
||||
- v2 [升级参考](/zh-CN/guide/faq)
|
||||
- v3 [变更](/zh-CN/guide/faq/#v3-变更)
|
||||
|
||||
<embed src="../../CHANGELOG.md"></embed>
|
88
web/docs/guide/faq.md
Normal file
88
web/docs/guide/faq.md
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: 💬 FAQ
|
||||
---
|
||||
|
||||
## Is there a charge for this feature?
|
||||
|
||||
GitHub Actions is provided free of charge by GitHub. Among them, the `Private` project has a monthly limit of 2000 times, [see details](https://github.com/settings/billing). The `Public` project is unlimited.
|
||||
|
||||
### Is there a rate limit?
|
||||
|
||||
Yes. The bottom layer of Action uses GitHub REST API. The general situation is 5000 times per hour. It is basically sufficient in principle, and it is also required to avoid invalid requests when defining Action. [Detailed view](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting).
|
||||
|
||||
## Are there any ready-made templates for reference?
|
||||
|
||||
Yes.
|
||||
|
||||
1. You can use this [GitHub Actions workflow template](https://github.com/actions-cool/.github) repository template
|
||||
2. Personal exercises and tests [Actions](https://github.com/actions-cool/test-issues-helper) repository
|
||||
3. You can also refer to the warehouse of [online users](#-who-is-using)
|
||||
|
||||
## I want to pause Actions, is there an easy way?
|
||||
|
||||
Yes, you can directly modify `actions`. For example: `actions:'create-comment'` is changed to `actions:'#create-comment'`. It is also convenient for recovery.
|
||||
|
||||
## So many versions, how to choose?
|
||||
|
||||
You can view the detailed [changelog](/changelog). The latest releases version is recommended.
|
||||
|
||||
- Version rules
|
||||
- Use two-level semantic version, such as v1, v1.1, v2, v2.1
|
||||
- v1 represents the initial version
|
||||
- The fixes and additions to the v1 version will be released to the v1.1 version
|
||||
- When the released v1.x runs stable for a certain period of time or undergoes refactoring, release the advanced v2.x version
|
||||
- After the v2 version, the version will be released strictly according to the three-level semantics, such as v2.0.0, v2.1.0
|
||||
|
||||
- Version selection
|
||||
- It is recommended to use the latest releases version. It can be seen in [releases](https://github.com/actions-cool/issues-helper/releases)
|
||||
- You can also refer to the update log below to select the version
|
||||
- The latest v1.x release code will be merged into the 1.x branch
|
||||
- After the v2 version, the v2 tag is supported, and the latest 2.x code will be synchronized
|
||||
- It also supports the direct use of branch versions. Such as:
|
||||
|
||||
```yml
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@main
|
||||
|
||||
# or
|
||||
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@1.x
|
||||
|
||||
# or
|
||||
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@v2
|
||||
```
|
||||
|
||||
## What should I pay attention to when upgrading from v1.x to v2?
|
||||
|
||||
There is only one difference between v1.12 and v2.0.0. That is, `require-permission` in `mark-duplicate` has added the default value `write`.
|
||||
|
||||
## v3 changelog
|
||||
|
||||
🚀 The refactoring of the v3 version is completed. The main changes are:
|
||||
|
||||
1. JS to TS
|
||||
2. Encapsulate the core functions of the issue into classes for helpers to use
|
||||
3. Unified prompt information
|
||||
4. Added automatic release script
|
||||
|
||||
Reference for functional changes:
|
||||
|
||||
- 🚀 New Feature
|
||||
- `mark-assignees`: Comment quick settings assignees
|
||||
- `find-issues`: Conditional query current warehouse issues
|
||||
- 🐞 Bug Fix
|
||||
- Fixed `find-comments` return result direction not working
|
||||
- Fix `lock-issues` lock and comment order issue
|
||||
- 🛠 Refactor
|
||||
- `contents` renamed to easy-to-understand `emoji`
|
||||
- `issue-emojis` renamed to `issue-emoji`
|
||||
- deleteComment updateComment no longer supports `out-comments`, keeping pure functionality
|
||||
- Remove title body default
|
||||
- `month-statistics` removed
|
||||
|
||||
## What should I do if there is no function I want here?
|
||||
|
||||
You can submit it in [What do you want?](https://github.com/actions-cool/issues-helper/discussions/18).
|
88
web/docs/guide/faq.zh-CN.md
Normal file
88
web/docs/guide/faq.zh-CN.md
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: 💬 FAQ
|
||||
---
|
||||
|
||||
## 该功能是否收费?
|
||||
|
||||
GitHub Actions 是由 GitHub 免费提供的。其中 `Private` 项目每月有 2000 次的限制,[具体查看](https://github.com/settings/billing)。`Public` 项目无限制。
|
||||
|
||||
### 有没有速率的限制?
|
||||
|
||||
有的。Action 底层使用的是 GitHub REST API。一般情况是每小时 5000 次。原则上基本是够用的,同时也要求在 Action 定义时,尽量避免无效的请求。[具体查看](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting)。
|
||||
|
||||
## 有没有现成的模板可以参考?
|
||||
|
||||
有的。
|
||||
|
||||
1. 你可以使用这个 [GitHub Actions workflow template](https://github.com/actions-cool/.github) 仓库的模板
|
||||
2. 个人练习和测试 [Actions](https://github.com/actions-cool/test-issues-helper) 的仓库
|
||||
3. 也可以来 [线上使用者](/zh-CN/#-谁在使用?) 的仓库参照
|
||||
|
||||
## 我想暂停 Actions,有没有简单的办法?
|
||||
|
||||
有的,你可以将直接修改 `actions`。例如:`actions: 'create-comment'` 修改为 `actions: '#create-comment'`。同时也方便恢复。
|
||||
|
||||
## 这么多版本,如何选择?
|
||||
|
||||
你可以查看详细的 [更新日志](/zh-CN/changelog)。推荐采用最新 releases 版本。
|
||||
|
||||
- 版本规则
|
||||
- 采用两级语义化版本,如v1、v1.1、v2、v2.1
|
||||
- v1 表示初始版本
|
||||
- 对 v1 版本的修复和新增会发布到 v1.1 版本
|
||||
- 当发布的 v1.x 运行一定时间稳定或进行重构时,发布进阶 v2.x 版本
|
||||
- v2 版本后会严格按照三级语义来发布版本,如 v2.0.0、v2.1.0
|
||||
|
||||
- 版本选择
|
||||
- 建议采用最新 releases 版本。可在 [releases](https://github.com/actions-cool/issues-helper/releases) 看到
|
||||
- 同时也可参照下面的更新日志来选择版本
|
||||
- 最新的 v1.x release 代码会合并到 1.x 分支中
|
||||
- v2 版本后支持使用 v2 tag,将同步最新 2.x 代码
|
||||
- 支持直接使用分支版本。如:
|
||||
|
||||
```yml
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@main
|
||||
|
||||
# or
|
||||
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@1.x
|
||||
|
||||
# or
|
||||
|
||||
- name: Issues Helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
```
|
||||
|
||||
## 从 v1.x 升级到 v2,有什么注意的地方吗?
|
||||
|
||||
v1.12 和 v2.0.0 版本的差别只有一处。即 `mark-duplicate` 中的 `require-permission` 增加了默认值 `write`。
|
||||
|
||||
## v3 变更
|
||||
|
||||
🚀 v3 版本重构完成,主要变更内容:
|
||||
|
||||
1. JS to TS
|
||||
2. 将 issue 核心功能封装成为类供 helper 使用
|
||||
3. 提示信息统一
|
||||
4. 增加自动发布脚本
|
||||
|
||||
功能变更参考:
|
||||
|
||||
- 🚀 New Feature
|
||||
- `mark-assignees`: 评论快捷设置 assignees
|
||||
- `find-issues`: 条件查询当前仓库 issues
|
||||
- 🐞 Bug Fix
|
||||
- 修复 `find-comments` 返回结果 direction 未起作用
|
||||
- 修复 `lock-issues` lock 与 comment 的顺序问题
|
||||
- 🛠 Refactor
|
||||
- contents 更名为容易理解的 emoji
|
||||
- `issue-emojis` 更名为 `issue-emoji`
|
||||
- deleteComment updateComment 不再支持 `out-comments`,保持纯粹功能
|
||||
- 移除 title body 默认值
|
||||
- `month-statistics` 移除
|
||||
|
||||
## 如果这里没有我想要的功能,该怎么办?
|
||||
|
||||
你可以在 issues 中提出。
|
@@ -1,4 +1,6 @@
|
||||
## Introduction
|
||||
---
|
||||
title: 🍭 Guide
|
||||
---
|
||||
|
||||
The Issues Helper is a GitHub Action that easily helps you automatically manage issues.
|
||||
|
@@ -1,4 +1,6 @@
|
||||
## 介 绍
|
||||
---
|
||||
title: 🍭 介 绍
|
||||
---
|
||||
|
||||
Issues 助手是一个轻松帮你自动管理 issues 的 GitHub Action。
|
||||
|
51
web/docs/guide/note.md
Normal file
51
web/docs/guide/note.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: 🎗 Note
|
||||
---
|
||||
|
||||
:::success{title="😊"}
|
||||
Here are some things I summarized in my use, I hope it can help you.
|
||||
:::
|
||||
|
||||
## Include judgment in `yml`
|
||||
|
||||
```yml
|
||||
if: contains(github.event.issue.body, 'ie') == false
|
||||
```
|
||||
- Triggered when the issue body does not contain `ie`
|
||||
- The js `includes()` syntax is not supported in the yml
|
||||
- Case is not checked, `IE` and also similar to `kiekk` can also be satisfied
|
||||
|
||||
[More](https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#functions).
|
||||
|
||||
## Pass value and output in `yml`
|
||||
|
||||
```
|
||||
with:
|
||||
actions: 'month-statistics'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
count-labels: 'true'
|
||||
```
|
||||
|
||||
- `count-labels`: Regardless of setting `true` or `'ture'`, all received in the program is in string format
|
||||
|
||||
At the same time, the output is also in string format. [See](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs).
|
||||
|
||||
- `check-result`: The judgment condition is `if: steps.xxid.outputs.check-result =='true'`
|
||||
|
||||
## `GitHub Actions bot` trigger
|
||||
|
||||
When an action is set, such as adding a label `x1` to an issue, Actions will automatically add a label `x2` to the issue.
|
||||
|
||||
But if this is done by `GitHub Actions bot` (that is, the token in the actions is not passed, or the default `token: ${{ secrets.GITHUB_TOKEN }}` is used), the actions of label `x2` will not be triggered.
|
||||
|
||||
ref: [GitHub docs](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token)
|
||||
|
||||
## `assignees` scope
|
||||
|
||||
- The owner or collaborator of the warehouse, if there is an organization, including members
|
||||
- Participants of the issue, including creators and commenters
|
||||
- Max 10
|
||||
|
||||
## Benchmark
|
||||
|
||||
For example: I use a Tag to trigger an Action, and the code that triggers the benchmark will follow the Action definition of the code corresponding to this Tag instead of the main branch code.
|
52
web/docs/guide/note.zh-CN.md
Normal file
52
web/docs/guide/note.zh-CN.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: 🎗 记 录
|
||||
---
|
||||
|
||||
:::success{title="😊"}
|
||||
这里记录自己在使用中总结的一些东西,希望可以帮助到你。
|
||||
:::
|
||||
|
||||
## `yml` 中包含判断
|
||||
|
||||
```yml
|
||||
if: contains(github.event.issue.body, 'ie') == false
|
||||
```
|
||||
|
||||
- 当 issue body 不包含 `ie` 触发
|
||||
- 测试 yml 中不支持 js `includes()` 语法
|
||||
- 大小写不校验,`IE` 还有同时类似 `kiekk` 也可满足
|
||||
|
||||
更多[查看](https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#functions)。
|
||||
|
||||
## `yml` 中传值和输出
|
||||
|
||||
```
|
||||
with:
|
||||
actions: 'month-statistics'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
count-labels: 'true'
|
||||
```
|
||||
|
||||
- `count-labels`:不管设置 `true` 还是 `'ture'`,在程序里接收到的都是字符串格式
|
||||
|
||||
同时输出的也是字符串格式。[参看](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs)。
|
||||
|
||||
- `check-result`:判断条件为 `if: steps.xxid.outputs.check-result == 'true'`
|
||||
|
||||
## `GitHub Actions bot` 触发
|
||||
|
||||
当设置了一个 Actions,如为给一个 issue 新增 label `x1` 时,Actions 自动为该 issue 增加 `x2` label。
|
||||
|
||||
但如果这个是由 `GitHub Actions bot` 完成的(即 actions 中 token 不传,或使用默认 `token: ${{ secrets.GITHUB_TOKEN }}`),则不会触发 label `x2` 的 Actions。
|
||||
|
||||
ref: [GitHub docs](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token)
|
||||
|
||||
## `assignees` 范围
|
||||
|
||||
- 仓库的所有者或协作者,若有组织,包括成员
|
||||
- issue 的参与者,包括创建者、评论者
|
||||
- 最多支持 10 个
|
||||
|
||||
## 运行基准
|
||||
|
||||
比如:我用 Tag 触发一个 Action,触发基准的代码就会走这个 Tag 对应代码的 Action 定义,而非主分支代码。
|
5
web/docs/guide/ref.md
Normal file
5
web/docs/guide/ref.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: 🎁 Reference
|
||||
---
|
||||
|
||||
<embed src="../../../README.md#RE-/<wrapper reference [^>]*>([\s\S]*?)<\/wrapper>/"></embed>
|
5
web/docs/guide/ref.zh-CN.md
Normal file
5
web/docs/guide/ref.zh-CN.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: 🎁 参 考
|
||||
---
|
||||
|
||||
<embed src="../../../README.zh-CN.md#RE-/<wrapper reference [^>]*>([\s\S]*?)<\/wrapper>/"></embed>
|
@@ -1,18 +1,20 @@
|
||||
## Quick start
|
||||
---
|
||||
title: ⚡️ Quick start
|
||||
---
|
||||
|
||||
### 1. New Action
|
||||
|
||||
Click Actions in the warehouse, if Actions have been added, the following interface will be displayed.
|
||||
|
||||

|
||||

|
||||
|
||||
Click `New workflow` to add.
|
||||
|
||||

|
||||

|
||||
|
||||
<Alert type="success">
|
||||
:::success{title="Tips"}
|
||||
You can click <Badge>set up a workflow yourself</Badge> to add a custom action, or you can apply a new action based on a template. <a target="_blank" href="https://github.com/actions-cool/.github">Templates</a>.
|
||||
</Alert>
|
||||
:::
|
||||
|
||||
### 2. Edit Action
|
||||
|
||||
@@ -33,7 +35,7 @@ jobs:
|
||||
steps:
|
||||
- name: help wanted
|
||||
if: github.event.label.name == 'help wanted'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -44,18 +46,18 @@ jobs:
|
||||
你好 @${{ github.event.issue.user.login }},我们完全同意你的提议/反馈,欢迎PR。
|
||||
```
|
||||
- `YML` syntax reference
|
||||
- [Workflow syntax for GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#on)
|
||||
- [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#about-yaml-syntax-for-workflows)
|
||||
- `name`: The workflow name
|
||||
- Actions workflow name, can be customized according to actual situation
|
||||
- `on`: The action trigger condition
|
||||
- Reference [Events that trigger workflows](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows)
|
||||
- Reference [Events that trigger workflows](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows)
|
||||
- `uses`: Use actions name
|
||||
- `uses: actions-cool/issues-helper@v1.2`。Please [refer](/en-US/changelog) to version selection
|
||||
- `uses: actions-cool/issues-helper@v2.0.0`。Please [refer](/changelog) to version selection
|
||||
- `issues-hepler` parameter
|
||||
- `actions`: The name of the function used, **required**. Support multiple, separated by commas, such as `create-comment,close-issue` means comment and close issue
|
||||
- `token`: A person who needs to have push permission token
|
||||
- [More view](/en-US/guide/ref#-token)
|
||||
- `issue-number`: Incoming parameter, here means the number of the current issue. If you are confused about the writing, you can [view](https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#github-context)
|
||||
- [More view](/guide/ref#-token)
|
||||
- `issue-number`: Incoming parameter, here means the number of the current issue. If you are confused about the writing, you can [view](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context)
|
||||
- `body`: Incoming parameters, here means the content of the current comment
|
||||
|
||||
### 3. Enable Action
|
||||
@@ -64,4 +66,4 @@ When you finish writing and submit to the master branch, you can automatically e
|
||||
|
||||
😏 I believe that you have a general understanding of `how to use`, do you want to try it quickly?
|
||||
|
||||
Please check the functions you need in [Basic](/en-US/base) and [Advanced](/en-US/advanced) for flexible reference.
|
||||
Please check the functions you need in [Basic](/base) and [Advanced](/advanced) for flexible reference.
|
@@ -1,18 +1,20 @@
|
||||
## 快速开始
|
||||
---
|
||||
title: ⚡️ 快速开始
|
||||
---
|
||||
|
||||
### 1. 新建 Action
|
||||
|
||||
点击仓库的 Actions,若已增加过 Actions,会显示如下界面。
|
||||
|
||||

|
||||

|
||||
|
||||
点击 `New workflow` 新增。
|
||||
|
||||

|
||||

|
||||
|
||||
<Alert type="success">
|
||||
:::success{title="提示"}
|
||||
你可以点击 <Badge>set up a workflow yourself</Badge> 新增一个自定义 action,也可以根据模板来套用新增一个 action。<a target="_blank" href="https://github.com/actions-cool/.github">模板使用</a>。
|
||||
</Alert>
|
||||
:::
|
||||
|
||||
### 2. 编写 Action
|
||||
|
||||
@@ -33,7 +35,7 @@ jobs:
|
||||
steps:
|
||||
- name: help wanted
|
||||
if: github.event.label.name == 'help wanted'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -44,18 +46,18 @@ jobs:
|
||||
你好 @${{ github.event.issue.user.login }},我们完全同意你的提议/反馈,欢迎PR。
|
||||
```
|
||||
- `YML` 语法参考
|
||||
- [GitHub Actions 语法](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#on)
|
||||
- [GitHub Actions 语法](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#about-yaml-syntax-for-workflows)
|
||||
- `name`:workflow 名称
|
||||
- Actions 流程名称,可根据实际情况自定义
|
||||
- `on`:action 触发条件
|
||||
- 参考 [工作流触发机制](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows)
|
||||
- 参考 [工作流触发机制](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows)
|
||||
- `uses`:使用 actions 名称
|
||||
- `uses: actions-cool/issues-helper@v1.2`。版本选择请 [参考](/changelog)
|
||||
- `uses: actions-cool/issues-helper@v2.0.0`。版本选择请 [参考](/zh-CN/changelog)
|
||||
- `issues-hepler` 参数
|
||||
- `actions`:使用功能的名称,**必填**。支持多个,需用逗号隔开,如 `create-comment,close-issue` 表示评论和关闭 issue
|
||||
- `token`:需拥有 push 权限的人员 token
|
||||
- 更多 [参考](/guide/ref#-token-说明)
|
||||
- `issue-number`:传入参数,这里表示当前 issue 的编号。如果你对写法疑惑,可 [查看](https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#github-context)
|
||||
- 更多 [参考](/zh-CN/guide/ref#-token-说明)
|
||||
- `issue-number`:传入参数,这里表示当前 issue 的编号。如果你对写法疑惑,可 [查看](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context)
|
||||
- `body`:传入参数,这里表示当前进行评论的内容
|
||||
|
||||
### 3. 启用 Action
|
||||
@@ -64,4 +66,4 @@ jobs:
|
||||
|
||||
😏 相信到这里你已经对 `如何使用` 有了大概的了解,是不是想快点尝试一下。
|
||||
|
||||
下面请在 [基 础](/base) 和 [进 阶](/advanced) 查看你需要的功能,灵活参考。
|
||||
下面请在 [基 础](/zh-CN/base) 和 [进 阶](/zh-CN/advanced) 查看你需要的功能,灵活参考。
|
@@ -3,22 +3,20 @@ title: Issues Helper
|
||||
order: 1
|
||||
hero:
|
||||
title: Issues Helper
|
||||
image: https://avatars1.githubusercontent.com/u/73879334?s=200&v=4
|
||||
desc: 🤖 A GitHub Action that easily helps you automatically manage issues
|
||||
description: 🤖 A GitHub Action that easily helps you automatically manage issues
|
||||
actions:
|
||||
- text: Quick start
|
||||
link: /en-US/guide/start
|
||||
link: /guide/start
|
||||
features:
|
||||
- icon: https://github.com/actions-cool/resources/blob/main/image/free.png?raw=true
|
||||
- emoji: 🎁
|
||||
title: Completely free
|
||||
desc: Use the Actions service provided by GitHub
|
||||
- icon: https://github.com/actions-cool/resources/blob/main/image/snap.png?raw=true
|
||||
description: Use the Actions service provided by GitHub
|
||||
- emoji: 👌
|
||||
title: Easy to use
|
||||
desc: Detailed tutorials and rich templates
|
||||
- icon: https://github.com/actions-cool/resources/blob/main/image/network.png?raw=true
|
||||
description: Detailed tutorials and rich templates
|
||||
- emoji: 🌍
|
||||
title: Easy hosting
|
||||
desc: As long as GitHub is not down, it will not be affected
|
||||
footer: Open-source MIT Licensed | Copyright © 2020-present<br />Powered by xrkffgg
|
||||
description: As long as GitHub is not down, it will not be affected
|
||||
---
|
||||
|
||||
## 🍭 Get started quickly
|
||||
@@ -38,7 +36,7 @@ jobs:
|
||||
steps:
|
||||
- name: help wanted
|
||||
if: github.event.label.name == 'help wanted'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -51,7 +49,7 @@ jobs:
|
||||
|
||||
## 💖 Who is using?
|
||||
|
||||
<code src="./users.tsx" inline />
|
||||
<embed src="../../README.md#RE-/<table>[^]+?[\r\n]<\/table>/"></embed>
|
||||
|
||||
## ⚡ Feedback
|
||||
|
@@ -3,22 +3,20 @@ title: Issues 助手
|
||||
order: 1
|
||||
hero:
|
||||
title: Issues 助手
|
||||
image: https://avatars1.githubusercontent.com/u/73879334?s=200&v=4
|
||||
desc: 🤖 一个轻松帮你自动管理 issues 的 GitHub Action
|
||||
description: 🤖 一个轻松帮你自动管理 issues 的 GitHub Action
|
||||
actions:
|
||||
- text: 快速开始
|
||||
link: /guide/start
|
||||
link: /zh-CN/guide/start
|
||||
features:
|
||||
- icon: https://github.com/actions-cool/resources/blob/main/image/free.png?raw=true
|
||||
- emoji: 🎁
|
||||
title: 完全免费
|
||||
desc: 使用 GitHub 自带提供的 Actions 服务
|
||||
- icon: https://github.com/actions-cool/resources/blob/main/image/snap.png?raw=true
|
||||
description: 使用 GitHub 自带提供的 Actions 服务
|
||||
- emoji: 👌
|
||||
title: 简单易用
|
||||
desc: 教程详细,模版丰富
|
||||
- icon: https://github.com/actions-cool/resources/blob/main/image/network.png?raw=true
|
||||
description: 教程详细,模版丰富
|
||||
- emoji: 🌍
|
||||
title: 轻松托管
|
||||
desc: 只要 GitHub 不宕机,它就不受影响
|
||||
footer: Open-source MIT Licensed | Copyright © 2020-present<br />Powered by xrkffgg
|
||||
description: 只要 GitHub 不宕机,它就不受影响
|
||||
---
|
||||
|
||||
## 🍭 快速上手
|
||||
@@ -38,7 +36,7 @@ jobs:
|
||||
steps:
|
||||
- name: help wanted
|
||||
if: github.event.label.name == 'help wanted'
|
||||
uses: actions-cool/issues-helper@v1.2
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -51,7 +49,7 @@ jobs:
|
||||
|
||||
## 💖 谁在使用?
|
||||
|
||||
<code src="./users.tsx" inline />
|
||||
<embed src="../../README.md#RE-/<table>[^]+?[\r\n]<\/table>/"></embed>
|
||||
|
||||
## ⚡ 反馈
|
||||
|
||||
@@ -60,3 +58,7 @@ jobs:
|
||||
- 通过 [Issue](https://github.com/actions-cool/issues-helper/issues) 报告 bug 或进行咨询
|
||||
- 通过 [Discussions](https://github.com/actions-cool/issues-helper/discussions) 进行讨论
|
||||
- 提交 [Pull Request](https://github.com/actions-cool/issues-helper/pulls) 改进 `issues-helper` 的代码
|
||||
|
||||
也欢迎加入 钉钉交流群
|
||||
|
||||

|
100
web/remark-plugins/index.ts
Normal file
100
web/remark-plugins/index.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { unistUtilVisit } from 'dumi';
|
||||
|
||||
const WRAPPER_OPEN_TAG = '<wrapper';
|
||||
const WRAPPER_CLOSE_TAG = '</wrapper>';
|
||||
|
||||
function remarkPlugin(opt) {
|
||||
return (tree, vFile) => {
|
||||
unistUtilVisit.visit(tree, 'html', (node, index, parent) => {
|
||||
if (node.value.startsWith(WRAPPER_OPEN_TAG)) {
|
||||
// get attributes
|
||||
const attrMatch = node.value.match(/(\w+)=['"]([^'"]+)['"]/g);
|
||||
|
||||
// convert attributes to object
|
||||
const attrObj = attrMatch.reduce((acc, cur) => {
|
||||
const split = cur.split('=');
|
||||
const key = split[0].trim().replace(/['"]/g, '');
|
||||
const value = split[1].trim().replace(/['"]/g, '');
|
||||
|
||||
if (value.match(/^-?\d+$/)) {
|
||||
acc[key] = Number(value);
|
||||
} else {
|
||||
acc[key] = value;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// transform headings
|
||||
const depth = Number.isInteger(attrObj['depth']) ? attrObj['depth'] : 0;
|
||||
unistUtilVisit.visit(tree, 'heading', (node: any) => {
|
||||
node.depth = node.depth - depth;
|
||||
});
|
||||
|
||||
// transform links
|
||||
unistUtilVisit.visit(tree, 'link', (node, index, parent) => {
|
||||
/**
|
||||
* remove blacktop link
|
||||
* zh-CN: url="#列-表", en-US: url="#List"
|
||||
*/
|
||||
if (['#列-表', '#List'].includes(node.url)) {
|
||||
if (parent && typeof index === 'number') {
|
||||
parent.children.splice(
|
||||
index,
|
||||
1,
|
||||
// ...('children' in node ? node.children : []) // 不需要保留子节点
|
||||
);
|
||||
}
|
||||
return unistUtilVisit.CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* redirect:
|
||||
* 1. token 说明
|
||||
*/
|
||||
if (node.url === '#token') {
|
||||
node.url = `./guide/ref${node.url}`;
|
||||
return unistUtilVisit.CONTINUE;
|
||||
}
|
||||
|
||||
if (['#emoji-类型', '#emoji-types'].includes(node.url)) {
|
||||
node.url = `./guide/ref${node.url}`;
|
||||
return unistUtilVisit.CONTINUE;
|
||||
}
|
||||
|
||||
if (node.url === '#github-docs') {
|
||||
node.url = `./guide/ref${node.url}`;
|
||||
return unistUtilVisit.CONTINUE;
|
||||
}
|
||||
|
||||
if (['#outputs-使用', '#outputs-use'].includes(node.url)) {
|
||||
node.url = `./guide/ref${node.url}`;
|
||||
return unistUtilVisit.CONTINUE;
|
||||
}
|
||||
|
||||
if (['#校验规则', '#check-rules'].includes(node.url)) {
|
||||
node.url = `./guide/ref${node.url}`;
|
||||
return unistUtilVisit.CONTINUE;
|
||||
}
|
||||
|
||||
if (node.url === '#comment-id') {
|
||||
node.url = `./guide/ref${node.url}`;
|
||||
return unistUtilVisit.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
(node.value === WRAPPER_CLOSE_TAG || node.value.startsWith(WRAPPER_OPEN_TAG)) &&
|
||||
parent &&
|
||||
typeof index === 'number'
|
||||
) {
|
||||
if (parent && typeof index === 'number') {
|
||||
parent.children.splice(index, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default remarkPlugin;
|
Reference in New Issue
Block a user