Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
chrispat committed Aug 4, 2019
0 parents commit 62b122f
Show file tree
Hide file tree
Showing 568 changed files with 99,070 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/close_stale.yml
@@ -0,0 +1,17 @@
name: "Close stale issues"
on:
push: {}
schedule:
- cron: 0 * * * *

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: bbq-beets/stale-bot@master
with:
stale_age_days: 0
wait_after_stale_days: 0
max_operations_per_run: 1
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" # todo: secrets.github_token
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
!node_modules/
__tests__/runner/*
11 changes: 11 additions & 0 deletions .prettierrc.json
@@ -0,0 +1,11 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}
22 changes: 22 additions & 0 deletions LICENSE
@@ -0,0 +1,22 @@

The MIT License (MIT)

Copyright (c) 2018 GitHub, Inc. and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
30 changes: 30 additions & 0 deletions README.md
@@ -0,0 +1,30 @@
# Close Stale Issues

To use, spin up a workflow. The following inputs are available:
* stale_age_days: The number of days old an issue can be before marking it stale (default 60)
* wait_after_stale_days: The number of days to wait to close an issue after it being marked stale (default 7)
* max_operations_per_run:The maximum number of operations per run, used to control rate limiting (default 30)
* stale_label: The label to apply when an item is stale (default 'Stale')
* stale_message: The message to post on the issue when tagging it

You'll need to map `GITHUB_TOKEN` to a PAT token for the identity you want to use to modify the issues:

Example workflow:
```
name: "Close stale issues"
on:
push: {}
schedule:
- cron: 0 * * * *
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: bbq-beets/stale-bot@master
with:
stale_age_days: 60
wait_after_stale_days: 7
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
```
3 changes: 3 additions & 0 deletions __tests__/main.test.ts
@@ -0,0 +1,3 @@
describe('TODO - Add a test suite', () => {
it('TODO - Add a test', async () => {});
});
27 changes: 27 additions & 0 deletions action.yml
@@ -0,0 +1,27 @@
name: 'Close Stale Issues'
description: 'Action to close stale issues'
author: 'GitHub'
inputs:
stale_age_days:
description: 'The number of days old an issue can be before marking it stale'
default: 60
wait_after_stale_days:
description: 'The number of days to wait to close an issue after it being marked stale'
default: 7
max_operations_per_run:
description: 'The maximum number of operations per run, used to control rate limiting'
default: 30
stale_label:
description: 'The label to apply when an item is stale'
default: 'Stale'
stale_message:
description: 'The message to post on the issue when tagging it'
default: >
Message goes here.
#This issue has not had any activity within the past ${{inputs.stale_age_days}} days. It will be
#closed in ${{wait_after_stale_days}} days if there is no more activity.
GITHUB_TOKEN:
description: 'The PAT for the identity to use to access to issues and to post messages'
runs:
using: 'node12'
main: 'lib/main.js'
22 changes: 22 additions & 0 deletions docs/contributors.md
@@ -0,0 +1,22 @@
# Contributors

### Checkin

- Do checkin source (src)
- Do checkin build output (lib)
- Do checkin runtime node_modules
- Do not checkin devDependency node_modules (husky can help see below)

### devDependencies

In order to handle correctly checking in node_modules without devDependencies, we run [Husky](https://github.com/typicode/husky) before each commit.
This step ensures that formatting and checkin rules are followed and that devDependencies are excluded. To make sure Husky runs correctly, please use the following workflow:

```
npm install # installs all devDependencies including Husky
git add abc.ext # Add the files you've changed. This should include files in src, lib, and node_modules (see above)
git commit -m "Informative commit message" # Commit. This will run Husky
```

During the commit step, Husky will take care of formatting all files with [Prettier](https://github.com/prettier/prettier) as well as pruning out devDependencies using `npm prune --production`.
It will also make sure these changes are appropriately included in your commit (no further work is needed)
11 changes: 11 additions & 0 deletions jest.config.js
@@ -0,0 +1,11 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}
124 changes: 124 additions & 0 deletions lib/main.js
@@ -0,0 +1,124 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const github = __importStar(require("@actions/github"));
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const args = getAndValidateArgs();
const octokit = new github.GitHub(args.token);
const issues = yield octokit.issues.listForRepo({
owner: args.repo_owner,
repo: args.repo_name,
state: 'open'
});
let operationsLeft = args.max_operations_per_run - 1;
for (var issue of issues.data.values()) {
core.debug(`found issue: ${issue.title} last updated ${issue.updated_at}`);
if (isLabeledStale(issue, args.stale_label)) {
if (wasLastUpdatedBefore(issue, args.wait_after_stale_days)) {
operationsLeft -= yield closeIssue(octokit, issue, args);
}
else {
continue;
}
}
else if (wasLastUpdatedBefore(issue, args.stale_age_days)) {
operationsLeft -= yield markStale(octokit, issue, args);
}
if (operationsLeft <= 0) {
core.warning(`performed ${args.max_operations_per_run} operations, exiting to avoid rate limit`);
break;
}
}
}
catch (error) {
core.error(error);
core.setFailed(error.message);
}
});
}
function isLabeledStale(issue, label) {
return issue.labels.filter(i => i.name === label).length > 0;
}
function wasLastUpdatedBefore(issue, num_days) {
const daysInMillis = (1000 * 60 * 60 * num_days);
const millisSinceLastUpdated = new Date().getTime() - new Date(issue.updated_at).getTime();
core.debug(`${daysInMillis}, ${millisSinceLastUpdated}`);
return millisSinceLastUpdated >= daysInMillis;
}
function markStale(octokit, issue, args) {
return __awaiter(this, void 0, void 0, function* () {
core.debug(`marking issue${issue.title} as stale`);
yield octokit.issues.createComment({
owner: args.repo_owner,
repo: args.repo_name,
issue_number: issue.number,
body: args.stale_message
});
yield octokit.issues.addLabels({
owner: args.repo_owner,
repo: args.repo_name,
issue_number: issue.number,
labels: [args.stale_label]
});
return 2; // operations performed
});
}
function closeIssue(octokit, issue, args) {
return __awaiter(this, void 0, void 0, function* () {
core.debug(`closing issue ${issue.title} for being stale`);
yield octokit.issues.update({
owner: args.repo_owner,
repo: args.repo_name,
issue_number: issue.number,
state: "closed"
});
return 1; // operations performed
});
}
function getAndValidateArgs() {
const args = {
token: process.env.GITHUB_TOKEN || '',
repo_owner: (process.env.GITHUB_REPOSITORY || '').split("/")[0],
repo_name: (process.env.GITHUB_REPOSITORY || '').split("/")[1],
stale_age_days: parseInt(core.getInput('stale_age_days')),
wait_after_stale_days: parseInt(core.getInput('wait_after_stale_days')),
max_operations_per_run: parseInt(core.getInput('max_operations_per_run')),
stale_label: core.getInput('stale_label'),
stale_message: core.getInput('stale_message')
};
if (!args.token) {
throw new Error('could not resolve token from GITHUB_TOKEN');
}
if (!args.repo_owner || !args.repo_name) {
throw new Error('could not resolve repo from GITHUB_REPOSITORY');
}
for (var stringInput of ["stale_label", "stale_message"]) {
if (!args[stringInput]) {
throw Error(`input ${stringInput} was empty`);
}
}
for (var numberInput of ["stale_age_days", "wait_after_stale_days", "max_operations_per_run"]) {
if (isNaN(args[numberInput])) {
throw Error(`input ${numberInput} did not parse to a valid integer`);
}
}
return args;
}
run();
15 changes: 15 additions & 0 deletions node_modules/.bin/semver

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions node_modules/.bin/semver.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions node_modules/.bin/uuid

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions node_modules/.bin/uuid.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions node_modules/.bin/which

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions node_modules/.bin/which.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions node_modules/@actions/core/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions node_modules/@actions/core/lib/command.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 62b122f

Please sign in to comment.