Skip to content

Commit 9913250

Browse files
authored
Merge pull request #1134 from jescalada/remove-getMissingData
refactor: replace `getMissingData` action with `checkEmptyBranch`
2 parents 43c6497 + 0d5b5aa commit 9913250

File tree

10 files changed

+226
-95
lines changed

10 files changed

+226
-95
lines changed

src/proxy/chain.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { attemptAutoApproval, attemptAutoRejection } from './actions/autoActions
55

66
const pushActionChain: ((req: any, action: Action) => Promise<Action>)[] = [
77
proc.push.parsePush,
8+
proc.push.checkEmptyBranch,
89
proc.push.checkRepoInAuthorisedList,
910
proc.push.checkCommitMessages,
1011
proc.push.checkAuthorEmails,
@@ -13,7 +14,6 @@ const pushActionChain: ((req: any, action: Action) => Promise<Action>)[] = [
1314
proc.push.writePack,
1415
proc.push.checkHiddenCommits,
1516
proc.push.checkIfWaitingAuth,
16-
proc.push.getMissingData,
1717
proc.push.preReceive,
1818
proc.push.getDiff,
1919
// run before clear remote
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Action, Step } from '../../actions';
2+
import simpleGit from 'simple-git';
3+
import { EMPTY_COMMIT_HASH } from '../constants';
4+
5+
const isEmptyBranch = async (action: Action) => {
6+
if (action.commitFrom === EMPTY_COMMIT_HASH) {
7+
try {
8+
const git = simpleGit(`${action.proxyGitPath}/${action.repoName}`);
9+
10+
const type = await git.raw(['cat-file', '-t', action.commitTo || '']);
11+
return type.trim() === 'commit';
12+
} catch (err) {
13+
console.log(`Commit ${action.commitTo} not found: ${err}`);
14+
}
15+
}
16+
17+
return false;
18+
};
19+
20+
const exec = async (req: any, action: Action): Promise<Action> => {
21+
const step = new Step('checkEmptyBranch');
22+
23+
if (action.commitData && action.commitData.length > 0) {
24+
return action;
25+
}
26+
27+
if (await isEmptyBranch(action)) {
28+
step.setError('Push blocked: Empty branch. Please make a commit before pushing a new branch.');
29+
action.addStep(step);
30+
step.error = true;
31+
return action;
32+
} else {
33+
step.setError('Push blocked: Commit data not found. Please contact an administrator for support.');
34+
action.addStep(step);
35+
step.error = true;
36+
return action;
37+
}
38+
};
39+
40+
exec.displayName = 'checkEmptyBranch.exec';
41+
42+
export { exec };

src/proxy/processors/push-action/checkUserPushPermission.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ const exec = async (req: any, action: Action): Promise<Action> => {
88
const user = action.user;
99

1010
if (!user) {
11-
console.log('Action has no user set. This may be due to a fast-forward ref update. Deferring to getMissingData action.');
11+
step.setError('Push blocked: User not found. Please contact an administrator for support.');
12+
action.addStep(step);
13+
step.error = true;
1214
return action;
1315
}
1416

@@ -17,8 +19,7 @@ const exec = async (req: any, action: Action): Promise<Action> => {
1719

1820
/**
1921
* Helper that validates the user's push permission.
20-
* This can be used by other actions that need it. For example, when the user is missing from the commit data,
21-
* validation is deferred to getMissingData, but the logic is the same.
22+
* This can be used by other actions that need it.
2223
* @param {string} user The user to validate
2324
* @param {Action} action The action object
2425
* @param {Step} step The step object

src/proxy/processors/push-action/getMissingData.ts

Lines changed: 0 additions & 76 deletions
This file was deleted.

src/proxy/processors/push-action/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { exec as checkCommitMessages } from './checkCommitMessages';
1414
import { exec as checkAuthorEmails } from './checkAuthorEmails';
1515
import { exec as checkUserPushPermission } from './checkUserPushPermission';
1616
import { exec as clearBareClone } from './clearBareClone';
17-
import { exec as getMissingData } from './getMissingData';
17+
import { exec as checkEmptyBranch } from './checkEmptyBranch';
1818

1919
export {
2020
parsePush,
@@ -33,5 +33,5 @@ export {
3333
checkAuthorEmails,
3434
checkUserPushPermission,
3535
clearBareClone,
36-
getMissingData,
36+
checkEmptyBranch,
3737
};

test/chain.test.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const mockLoader = {
1818
const initMockPushProcessors = (sinon) => {
1919
const mockPushProcessors = {
2020
parsePush: sinon.stub(),
21+
checkEmptyBranch: sinon.stub(),
2122
audit: sinon.stub(),
2223
checkRepoInAuthorisedList: sinon.stub(),
2324
checkCommitMessages: sinon.stub(),
@@ -33,9 +34,9 @@ const initMockPushProcessors = (sinon) => {
3334
clearBareClone: sinon.stub(),
3435
scanDiff: sinon.stub(),
3536
blockForAuth: sinon.stub(),
36-
getMissingData: sinon.stub(),
3737
};
3838
mockPushProcessors.parsePush.displayName = 'parsePush';
39+
mockPushProcessors.checkEmptyBranch.displayName = 'checkEmptyBranch';
3940
mockPushProcessors.audit.displayName = 'audit';
4041
mockPushProcessors.checkRepoInAuthorisedList.displayName = 'checkRepoInAuthorisedList';
4142
mockPushProcessors.checkCommitMessages.displayName = 'checkCommitMessages';
@@ -51,7 +52,6 @@ const initMockPushProcessors = (sinon) => {
5152
mockPushProcessors.clearBareClone.displayName = 'clearBareClone';
5253
mockPushProcessors.scanDiff.displayName = 'scanDiff';
5354
mockPushProcessors.blockForAuth.displayName = 'blockForAuth';
54-
mockPushProcessors.getMissingData.displayName = 'getMissingData';
5555
return mockPushProcessors;
5656
};
5757
const mockPreProcessors = {
@@ -127,6 +127,7 @@ describe('proxy chain', function () {
127127
const continuingAction = { type: 'push', continue: () => true, allowPush: false };
128128
mockPreProcessors.parseAction.resolves({ type: 'push' });
129129
mockPushProcessors.parsePush.resolves(continuingAction);
130+
mockPushProcessors.checkEmptyBranch.resolves(continuingAction);
130131
mockPushProcessors.checkRepoInAuthorisedList.resolves(continuingAction);
131132
mockPushProcessors.checkCommitMessages.resolves(continuingAction);
132133
mockPushProcessors.checkAuthorEmails.resolves(continuingAction);
@@ -152,7 +153,7 @@ describe('proxy chain', function () {
152153
expect(mockPushProcessors.pullRemote.called).to.be.true;
153154
expect(mockPushProcessors.checkHiddenCommits.called).to.be.true;
154155
expect(mockPushProcessors.writePack.called).to.be.true;
155-
expect(mockPushProcessors.getMissingData.called).to.be.false;
156+
expect(mockPushProcessors.checkEmptyBranch.called).to.be.true;
156157
expect(mockPushProcessors.audit.called).to.be.true;
157158

158159
expect(result.type).to.equal('push');
@@ -165,6 +166,7 @@ describe('proxy chain', function () {
165166
const continuingAction = { type: 'push', continue: () => true, allowPush: false };
166167
mockPreProcessors.parseAction.resolves({ type: 'push' });
167168
mockPushProcessors.parsePush.resolves(continuingAction);
169+
mockPushProcessors.checkEmptyBranch.resolves(continuingAction);
168170
mockPushProcessors.checkRepoInAuthorisedList.resolves(continuingAction);
169171
mockPushProcessors.checkCommitMessages.resolves(continuingAction);
170172
mockPushProcessors.checkAuthorEmails.resolves(continuingAction);
@@ -182,6 +184,7 @@ describe('proxy chain', function () {
182184

183185
expect(mockPreProcessors.parseAction.called).to.be.true;
184186
expect(mockPushProcessors.parsePush.called).to.be.true;
187+
expect(mockPushProcessors.checkEmptyBranch.called).to.be.true;
185188
expect(mockPushProcessors.checkRepoInAuthorisedList.called).to.be.true;
186189
expect(mockPushProcessors.checkCommitMessages.called).to.be.true;
187190
expect(mockPushProcessors.checkAuthorEmails.called).to.be.true;
@@ -190,7 +193,6 @@ describe('proxy chain', function () {
190193
expect(mockPushProcessors.pullRemote.called).to.be.true;
191194
expect(mockPushProcessors.checkHiddenCommits.called).to.be.true;
192195
expect(mockPushProcessors.writePack.called).to.be.true;
193-
expect(mockPushProcessors.getMissingData.called).to.be.false;
194196
expect(mockPushProcessors.audit.called).to.be.true;
195197

196198
expect(result.type).to.equal('push');
@@ -203,6 +205,7 @@ describe('proxy chain', function () {
203205
const continuingAction = { type: 'push', continue: () => true, allowPush: false };
204206
mockPreProcessors.parseAction.resolves({ type: 'push' });
205207
mockPushProcessors.parsePush.resolves(continuingAction);
208+
mockPushProcessors.checkEmptyBranch.resolves(continuingAction);
206209
mockPushProcessors.checkRepoInAuthorisedList.resolves(continuingAction);
207210
mockPushProcessors.checkCommitMessages.resolves(continuingAction);
208211
mockPushProcessors.checkAuthorEmails.resolves(continuingAction);
@@ -217,12 +220,12 @@ describe('proxy chain', function () {
217220
mockPushProcessors.clearBareClone.resolves(continuingAction);
218221
mockPushProcessors.scanDiff.resolves(continuingAction);
219222
mockPushProcessors.blockForAuth.resolves(continuingAction);
220-
mockPushProcessors.getMissingData.resolves(continuingAction);
221223

222224
const result = await chain.executeChain(req);
223225

224226
expect(mockPreProcessors.parseAction.called).to.be.true;
225227
expect(mockPushProcessors.parsePush.called).to.be.true;
228+
expect(mockPushProcessors.checkEmptyBranch.called).to.be.true;
226229
expect(mockPushProcessors.checkRepoInAuthorisedList.called).to.be.true;
227230
expect(mockPushProcessors.checkCommitMessages.called).to.be.true;
228231
expect(mockPushProcessors.checkAuthorEmails.called).to.be.true;
@@ -238,7 +241,6 @@ describe('proxy chain', function () {
238241
expect(mockPushProcessors.scanDiff.called).to.be.true;
239242
expect(mockPushProcessors.blockForAuth.called).to.be.true;
240243
expect(mockPushProcessors.audit.called).to.be.true;
241-
expect(mockPushProcessors.getMissingData.called).to.be.true;
242244

243245
expect(result.type).to.equal('push');
244246
expect(result.allowPush).to.be.false;
@@ -299,6 +301,7 @@ describe('proxy chain', function () {
299301

300302
mockPreProcessors.parseAction.resolves(action);
301303
mockPushProcessors.parsePush.resolves(action);
304+
mockPushProcessors.checkEmptyBranch.resolves(action);
302305
mockPushProcessors.checkRepoInAuthorisedList.resolves(action);
303306
mockPushProcessors.checkCommitMessages.resolves(action);
304307
mockPushProcessors.checkAuthorEmails.resolves(action);
@@ -320,7 +323,6 @@ describe('proxy chain', function () {
320323
mockPushProcessors.clearBareClone.resolves(action);
321324
mockPushProcessors.scanDiff.resolves(action);
322325
mockPushProcessors.blockForAuth.resolves(action);
323-
mockPushProcessors.getMissingData.resolves(action);
324326
const dbStub = sinon.stub(db, 'authorise').resolves(true);
325327

326328
const result = await chain.executeChain(req);
@@ -347,6 +349,7 @@ describe('proxy chain', function () {
347349

348350
mockPreProcessors.parseAction.resolves(action);
349351
mockPushProcessors.parsePush.resolves(action);
352+
mockPushProcessors.checkEmptyBranch.resolves(action);
350353
mockPushProcessors.checkRepoInAuthorisedList.resolves(action);
351354
mockPushProcessors.checkCommitMessages.resolves(action);
352355
mockPushProcessors.checkAuthorEmails.resolves(action);
@@ -368,7 +371,6 @@ describe('proxy chain', function () {
368371
mockPushProcessors.clearBareClone.resolves(action);
369372
mockPushProcessors.scanDiff.resolves(action);
370373
mockPushProcessors.blockForAuth.resolves(action);
371-
mockPushProcessors.getMissingData.resolves(action);
372374

373375
const dbStub = sinon.stub(db, 'reject').resolves(true);
374376

@@ -396,6 +398,7 @@ describe('proxy chain', function () {
396398

397399
mockPreProcessors.parseAction.resolves(action);
398400
mockPushProcessors.parsePush.resolves(action);
401+
mockPushProcessors.checkEmptyBranch.resolves(action);
399402
mockPushProcessors.checkRepoInAuthorisedList.resolves(action);
400403
mockPushProcessors.checkCommitMessages.resolves(action);
401404
mockPushProcessors.checkAuthorEmails.resolves(action);
@@ -417,7 +420,6 @@ describe('proxy chain', function () {
417420
mockPushProcessors.clearBareClone.resolves(action);
418421
mockPushProcessors.scanDiff.resolves(action);
419422
mockPushProcessors.blockForAuth.resolves(action);
420-
mockPushProcessors.getMissingData.resolves(action);
421423

422424
const error = new Error('Database error');
423425

@@ -444,6 +446,7 @@ describe('proxy chain', function () {
444446

445447
mockPreProcessors.parseAction.resolves(action);
446448
mockPushProcessors.parsePush.resolves(action);
449+
mockPushProcessors.checkEmptyBranch.resolves(action);
447450
mockPushProcessors.checkRepoInAuthorisedList.resolves(action);
448451
mockPushProcessors.checkCommitMessages.resolves(action);
449452
mockPushProcessors.checkAuthorEmails.resolves(action);
@@ -465,7 +468,6 @@ describe('proxy chain', function () {
465468
mockPushProcessors.clearBareClone.resolves(action);
466469
mockPushProcessors.scanDiff.resolves(action);
467470
mockPushProcessors.blockForAuth.resolves(action);
468-
mockPushProcessors.getMissingData.resolves(action);
469471

470472
const error = new Error('Database error');
471473

test/processors/checkCommitMessages.test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ describe('checkCommitMessages', () => {
9797
});
9898

9999
it('should not error when commit data is empty', async () => {
100-
// Empty commit data is a valid scenario that happens when making a branch from an unapproved commit
101-
// This is remedied in the getMissingData.exec action
100+
// Empty commit data happens when making a branch from an unapproved commit
101+
// or when pushing an empty branch or deleting a branch
102+
// This is handled in the checkEmptyBranch.exec action
102103
action.commitData = [];
103104
const result = await exec(req, action);
104105

0 commit comments

Comments
 (0)