Skip to content

Commit

Permalink
Check SHA1 hashes for blobs locally (#55)
Browse files Browse the repository at this point in the history
* Check SHA1 hashes for blobs locally
Fixes #53

* Adding functional test

* Realized I was trying to hash the encoded contents

* Turns out git prefixes the file and then hashes it

* Let's try that again

* Debugging

* 🤦

* Fine I just won't use if

* I don't know anymore
  • Loading branch information
cooperbenson-qz authored Nov 23, 2020
1 parent 6a812aa commit cffb18a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 7 deletions.
20 changes: 18 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Generate file to commit
run: 'echo "$(date): Testing ${GITHUB_SHA}" > test.txt'
- name: Generate files to commit
run: |
echo "$(date): Testing ${GITHUB_SHA}" > test.txt
echo "static value" > static.txt
- name: Run action against test with default token
uses: ./
with:
Expand All @@ -66,3 +68,17 @@ jobs:
branch: protected-test
message: ':robot: Test commit'
glob-patterns: test.txt
- name: Run action against unchanged file
id: unchanged-commit
uses: ./
with:
branch: test
message: ':robot: Test commit of static.txt'
glob-patterns: static.txt
- name: Fail if unchanged file was committed
run: |
if [[ -n "${{steps.unchanged-commit.outputs.sha}}" ]]
then
echo "::error::Action commited the unchanged file"
exit 1
fi
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions src/commitFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {GitHub} from '@actions/github/lib/utils';
import {Endpoints} from '@octokit/types';
import * as core from '@actions/core';
import _ from 'lodash';
import {computeBlobHashB64String} from './utils/hash';

export type Octokit = InstanceType<typeof GitHub>;
type Tree = Endpoints['POST /repos/:owner/:repo/git/trees']['parameters']['tree'];
Expand Down Expand Up @@ -48,13 +49,15 @@ export async function createOrUpdateFiles(
throw Error('Refusing to replace non-blob tree entry');
}

const {data: blob} = await octokit.git.createBlob({owner, repo, content, encoding: 'base64'});
if (previousEntry?.sha !== blob.sha) {
const hash = computeBlobHashB64String(content);
if (hash !== previousEntry?.sha) {
const {data: blob} = await octokit.git.createBlob({owner, repo, content, encoding: 'base64'});

tree.push({
path,
sha: blob.sha,
type: 'blob',
// TODO: Grab previous mode if it exists. Right now types are getting in the way
// TODO(#44): Set to 100755 if file is executable
mode: '100644',
});
} else {
Expand Down
12 changes: 12 additions & 0 deletions src/utils/hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {createHash} from 'crypto';

/**
* Compute the git blob hash for a base64 encoded string
* @param b64string Base64 encoded string
*/
export function computeBlobHashB64String(b64string: string): string {
const contents = Buffer.from(b64string, 'base64');
const buf = Buffer.concat([Buffer.from(`blob ${contents.length}\0`), contents]);
const hasher = createHash('sha1');
return hasher.update(buf).digest('hex');
}

0 comments on commit cffb18a

Please sign in to comment.