Skip to content

Commit 0587be7

Browse files
initial commit
1 parent f1590b1 commit 0587be7

11 files changed

+6485
-2
lines changed

.editorconfig

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# http://editorconfig.org
2+
root = true
3+
4+
[*]
5+
charset = utf-8
6+
end_of_line = lf
7+
indent_size = 2
8+
indent_style = space
9+
insert_final_newline = true
10+
max_line_length = 120
11+
trim_trailing_whitespace = true
12+
13+
[*.md]
14+
max_line_length = 0
15+
trim_trailing_whitespace = false
16+
17+
[COMMIT_EDITMSG]
18+
max_line_length = 0

.gitignore

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
lerna-debug.log*
8+
9+
# Diagnostic reports (https://nodejs.org/api/report.html)
10+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11+
12+
# Runtime data
13+
pids
14+
*.pid
15+
*.seed
16+
*.pid.lock
17+
18+
# Directory for instrumented libs generated by jscoverage/JSCover
19+
lib-cov
20+
21+
# Coverage directory used by tools like istanbul
22+
coverage
23+
*.lcov
24+
25+
# nyc test coverage
26+
.nyc_output
27+
28+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29+
.grunt
30+
31+
# Bower dependency directory (https://bower.io/)
32+
bower_components
33+
34+
# node-waf configuration
35+
.lock-wscript
36+
37+
# Compiled binary addons (https://nodejs.org/api/addons.html)
38+
build/Release
39+
40+
# Dependency directories
41+
node_modules/
42+
jspm_packages/
43+
44+
# Snowpack dependency directory (https://snowpack.dev/)
45+
web_modules/
46+
47+
# TypeScript cache
48+
*.tsbuildinfo
49+
50+
# Optional npm cache directory
51+
.npm
52+
53+
# Optional eslint cache
54+
.eslintcache
55+
56+
# Microbundle cache
57+
.rpt2_cache/
58+
.rts2_cache_cjs/
59+
.rts2_cache_es/
60+
.rts2_cache_umd/
61+
62+
# Optional REPL history
63+
.node_repl_history
64+
65+
# Output of 'npm pack'
66+
*.tgz
67+
68+
# Yarn Integrity file
69+
.yarn-integrity
70+
71+
# dotenv environment variables file
72+
.env
73+
.env.test
74+
75+
# parcel-bundler cache (https://parceljs.org/)
76+
.cache
77+
.parcel-cache
78+
79+
# Next.js build output
80+
.next
81+
out
82+
83+
# Nuxt.js build / generate output
84+
.nuxt
85+
86+
# Gatsby files
87+
.cache/
88+
# Comment in the public line in if your project uses Gatsby and not Next.js
89+
# https://nextjs.org/blog/next-9-1#public-directory-support
90+
# public
91+
92+
# vuepress build output
93+
.vuepress/dist
94+
95+
# Serverless directories
96+
.serverless/
97+
98+
# FuseBox cache
99+
.fusebox/
100+
101+
# DynamoDB Local files
102+
.dynamodb/
103+
104+
# TernJS port file
105+
.tern-port
106+
107+
# Stores VSCode versions used for testing VSCode extensions
108+
.vscode-test
109+
110+
# yarn v2
111+
.yarn/cache
112+
.yarn/unplugged
113+
.yarn/build-state.yml
114+
.yarn/install-state.gz
115+
.pnp.*

.jshintrc

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"node": true,
3+
"esversion": 9,
4+
"camelcase": true,
5+
"curly": true,
6+
"eqeqeq": true,
7+
"evil": true,
8+
"freeze": true,
9+
"indent": 2,
10+
"newcap": true,
11+
"quotmark": "single",
12+
"maxlen": 120,
13+
"eqnull": true,
14+
"funcscope": true,
15+
"globals": {}
16+
}

.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
scripts-prepend-node-path=true

README.md

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1-
# keepalive-workflow
2-
GitHub action to prevent GitHub from suspending your cronjob based trigger due to repository inactivity
1+
# Keepalive Workflow
2+
GitHub action to prevent GitHub from suspending your cronjob based triggers due to repository inactivity
3+
4+
### Why ?
5+
GitHub will suspend the scheduled trigger for GitHub action workflows if there is no commit in the repository for the past 60 days. The cron based triggers won't run unless a new commit is made.
6+
![preview](https://user-images.githubusercontent.com/8397274/105174930-4303e100-5b49-11eb-90ed-95a55697582f.png)
7+
8+
### What ?
9+
This workflow will automatically create a dummy commit in your repo if the last commit in your repo is 50 days (default) ago.
10+
This will keep the cronjob trigger active, so that it will run indefinitely without getting suspended by GitHub for inactivity.

action.yml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: 'Keepalive Workflow'
2+
author: 'Gautam Krishna R'
3+
description: 'GitHub action to prevent GitHub from suspending your cronjob based triggers due to repository inactivity'
4+
5+
inputs:
6+
gh_token:
7+
description: 'GitHub access token with Repo scope'
8+
required: false
9+
default: ${{ github.token }}
10+
commit_message:
11+
description: "Commit message used while committing to the repo"
12+
default: "Automated commit by Keepalive Workflow to keep the repository active"
13+
required: false
14+
committer_username:
15+
description: "Username used while committing to the repo"
16+
default: "keepalive-workflow-bot"
17+
required: false
18+
committer_email:
19+
description: "Email id used while committing to the repo"
20+
default: "[email protected]"
21+
required: false
22+
time_elapsed:
23+
description: "Time elapsed from the last commit to trigger a new automated commit (in days)"
24+
default: "50"
25+
required: false
26+
27+
runs:
28+
using: node12
29+
main: dist/index.js
30+
branding:
31+
icon: 'truck'
32+
color: 'blue'

dist/index.js

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.js

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
const core = require('@actions/core');
2+
const {execute} = require('util');
3+
4+
/**
5+
* Keep Alive Workflow
6+
* @type {Promise<string>}
7+
*/
8+
const KeepAliveWorkflow = new Promise(async (resolve, reject) => {
9+
try {
10+
// Getting config
11+
const githubToken = core.getInput('gh_token');
12+
const committerUsername = core.getInput('committer_username');
13+
const committerEmail = core.getInput('committer_email');
14+
const commitMessage = core.getInput('commit_message');
15+
const timeElapsed = parseInt(core.getInput('time_elapsed'));
16+
17+
// Calculating the last commit date
18+
const {outputData} = await execute('git', ['--no-pager', 'log', '-1', '--format=%ct'],
19+
{encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe']});
20+
21+
const commitDate = new Date(parseInt(outputData, 10) * 1000);
22+
const diffInDays = Math.round((new Date() - commitDate) / (1000 * 60 * 60 * 24));
23+
24+
if (diffInDays > timeElapsed) {
25+
// Do dummy commit if elapsed time is greater than 50 (default) days
26+
core.info('Doing dummy commit to keep repository active');
27+
await execute('git', [
28+
'config',
29+
'--global',
30+
'user.email',
31+
committerEmail,
32+
]);
33+
await execute('git', [
34+
'remote',
35+
'set-url',
36+
'origin',
37+
`https://${githubToken}@github.com/${process.env.GITHUB_REPOSITORY}.git`
38+
]);
39+
await execute('git', [
40+
'config',
41+
'--global',
42+
'user.name',
43+
committerUsername
44+
]);
45+
await execute('git', [
46+
'commit',
47+
'--allow-empty',
48+
'-m',
49+
`"${commitMessage}"`]);
50+
resolve('Dummy commit created...');
51+
} else {
52+
resolve('Nothing to do');
53+
}
54+
} catch (e) {
55+
reject(e.toString());
56+
}
57+
});
58+
59+
KeepAliveWorkflow
60+
.then((message) => {
61+
core.info(message);
62+
process.exit(1);
63+
})
64+
.catch((error) => {
65+
core.error(error);
66+
process.exit(1);
67+
});

package.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "keepalive-workflow",
3+
"version": "1.0.0",
4+
"description": "GitHub action to prevent GitHub from suspending your cronjob based trigger due to repository inactivity",
5+
"main": "index.js",
6+
"scripts": {
7+
"build": "parcel build --no-source-maps --target=node --bundle-node-modules index.js",
8+
"lint": "jshint --exclude='node_modules/' *.js"
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "git+https://github.com/gautamkrishnar/keepalive-workflow.git"
13+
},
14+
"keywords": [
15+
"github",
16+
"workflow",
17+
"keepalive",
18+
"action"
19+
],
20+
"author": "Gautam krishna R <[email protected]> (https://www.github.com/gautamkrishnar)",
21+
"license": "GPL-3.0",
22+
"bugs": {
23+
"url": "https://github.com/gautamkrishnar/keepalive-workflow/issues"
24+
},
25+
"homepage": "https://github.com/gautamkrishnar/keepalive-workflow#readme",
26+
"dependencies": {
27+
"@actions/core": "^1.5.0",
28+
"process": "latest"
29+
},
30+
"devDependencies": {
31+
"jshint": "^2.12.0",
32+
"mocha": "^8.1.3",
33+
"parcel-bundler": "^1.12.4",
34+
"start-server-and-test": "^1.11.3"
35+
}
36+
}

util.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const {spawn} = require('child_process');
2+
3+
/**
4+
* Executes a command and returns its result as promise
5+
* @param cmd {string} command to execute
6+
* @param args {array} command line args
7+
* @param options {Object} extra options
8+
* @return {Promise<Object>}
9+
*/
10+
const execute = (cmd, args = [], options = {}) => new Promise((resolve, reject) => {
11+
let outputData = '';
12+
const optionsToCLI = {
13+
...options
14+
};
15+
if (!optionsToCLI.stdio) {
16+
Object.assign(optionsToCLI, {stdio: ['inherit', 'inherit', 'inherit']});
17+
}
18+
const app = spawn(cmd, args, optionsToCLI);
19+
if (app.stdout) {
20+
// Only needed for pipes
21+
app.stdout.on('data', function (data) {
22+
outputData += data.toString();
23+
});
24+
}
25+
26+
app.on('close', (code) => {
27+
if (code !== 0) {
28+
return reject({code, outputData});
29+
}
30+
return resolve({code, outputData});
31+
});
32+
app.on('error', () => reject({code: 1, outputData}));
33+
});
34+
35+
module.exports = {
36+
execute
37+
};

0 commit comments

Comments
 (0)