Merge pull request #71 from pre-commit/pre-commit-ci-update-config
[airflow-pre-commit-action.git] / index.js
index 64bdac2e77d8568f8fe23e05315658c55b77bb8b..9adf9a158501e6690f0aed2bc657b503273ada28 100644 (file)
--- a/index.js
+++ b/index.js
@@ -1,13 +1,35 @@
+const child_process = require('child_process');
+const crypto = require('crypto');
+const fs = require('fs');
+const os = require('os');
+const path = require('path');
+
+const cache = require('@actions/cache');
 const core = require('@actions/core');
 const exec = require('@actions/exec');
 const github = require('@actions/github');
+const tr = require('@actions/exec/lib/toolrunner');
+
+function hashString(content) {
+    const sha256 = crypto.createHash('sha256');
+    return sha256.update(content).digest('hex');
+}
+
+function getPythonVersion() {
+    const args = ['-c', 'import sys;print(sys.executable+"\\n"+sys.version)'];
+    const res = child_process.spawnSync('python', args);
+    if (res.status !== 0) {
+        throw 'python version check failed';
+    }
+    return res.stdout.toString();
+}
 
-const ARGS = [
-    'run', '--all-files', '--show-diff-on-failure', '--color=always'
-];
+function hashFile(filePath) {
+    return hashString(fs.readFileSync(filePath).toString());
+}
 
 function addToken(url, token) {
-    return url.replace(/^https:\/\//, `https://x-access-token:${token}@`)
+    return url.replace(/^https:\/\//, `https://x-access-token:${token}@`);
 }
 
 async function main() {
@@ -16,15 +38,30 @@ async function main() {
         await exec.exec('pip', ['freeze', '--local']);
     });
 
+    const args = [
+        'run',
+        '--show-diff-on-failure',
+        '--color=always',
+        ...tr.argStringToArray(core.getInput('extra_args')),
+    ];
     const token = core.getInput('token');
     const pr = github.context.payload.pull_request;
     const push = !!token && !!pr;
-    const ret = await exec.exec('pre-commit', ARGS, {ignoreReturnCode: push});
+
+    const cachePaths = [path.join(os.homedir(), '.cache', 'pre-commit')];
+    const py = getPythonVersion();
+    const cacheKey = `pre-commit-2-${hashString(py)}-${hashFile('.pre-commit-config.yaml')}`;
+    const restored = await cache.restoreCache(cachePaths, cacheKey);
+    const ret = await exec.exec('pre-commit', args, {ignoreReturnCode: push});
+    if (!restored) {
+        await cache.saveCache(cachePaths, cacheKey);
+    }
+
     if (ret && push) {
         // actions do not run on pushes made by actions.
         // need to make absolute sure things are good before pushing
         // TODO: is there a better way around this limitation?
-        await exec.exec('pre-commit', ARGS);
+        await exec.exec('pre-commit', args);
 
         const diff = await exec.exec(
             'git', ['diff', '--quiet'], {ignoreReturnCode: true}
@@ -41,8 +78,7 @@ async function main() {
 
                 await exec.exec('git', ['commit', '-am', 'pre-commit fixes']);
                 const url = addToken(pr.head.repo.clone_url, token);
-                await exec.exec('git', ['remote', 'set-url', 'origin', url]);
-                await exec.exec('git', ['push', 'origin', 'HEAD']);
+                await exec.exec('git', ['push', url, 'HEAD']);
             });
         }
     }