mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
Handle silent failures for git push operation (#2432)
This commit is contained in:
parent
886c4d75b5
commit
b29be4ac2b
@ -40,7 +40,9 @@
|
||||
"asyncArrow": "always"
|
||||
}
|
||||
],
|
||||
"filenames/match-exported": ["error", "kebab"]
|
||||
"filenames/match-exported": ["error", "kebab"],
|
||||
"flowtype/array-style-simple-type": "error",
|
||||
"flowtype/array-style-complex-type": "error"
|
||||
},
|
||||
"settings": {
|
||||
"flowtype": {
|
||||
|
6
packages/insomnia-app/app/__mocks__/isomorphic-git.js
Normal file
6
packages/insomnia-app/app/__mocks__/isomorphic-git.js
Normal file
@ -0,0 +1,6 @@
|
||||
// eslint-disable-next-line filenames/match-exported
|
||||
const git = jest.requireActual('isomorphic-git');
|
||||
const mock = jest.genMockFromModule('isomorphic-git');
|
||||
|
||||
git.push = mock.push;
|
||||
module.exports = git;
|
@ -2,6 +2,8 @@ import GitVCS, { GIT_CLONE_DIR, GIT_INSOMNIA_DIR } from '../git-vcs';
|
||||
import { setupDateMocks } from './util';
|
||||
import { MemPlugin } from '../mem-plugin';
|
||||
import path from 'path';
|
||||
import * as git from 'isomorphic-git';
|
||||
|
||||
jest.mock('path');
|
||||
|
||||
describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
|
||||
@ -144,6 +146,20 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('push()', () => {
|
||||
it('should throw an exception when push response contains errors', async () => {
|
||||
git.push.mockReturnValue({
|
||||
ok: ['unpack'],
|
||||
errors: ['refs/heads/master pre-receive hook declined'],
|
||||
});
|
||||
|
||||
const vcs = new GitVCS();
|
||||
await expect(vcs.push()).rejects.toThrowError(
|
||||
'Push rejected with errors: ["refs/heads/master pre-receive hook declined"].\n\nGo to View > Toggle DevTools > Console for more information.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('undoPendingChanges()', () => {
|
||||
it('should remove pending changes from all tracked files', async () => {
|
||||
const folder = path.join(GIT_INSOMNIA_DIR, 'folder');
|
||||
|
@ -4,6 +4,7 @@ import { trackEvent } from '../../common/analytics';
|
||||
import { httpPlugin } from './http';
|
||||
import { convertToOsSep, convertToPosixSep } from './path-sep';
|
||||
import path from 'path';
|
||||
import EventEmitter from 'events';
|
||||
|
||||
export type GitAuthor = {|
|
||||
name: string,
|
||||
@ -36,6 +37,12 @@ export type GitLogEntry = {|
|
||||
},
|
||||
|};
|
||||
|
||||
export type PushResponse = {
|
||||
ok?: Array<string>,
|
||||
errors?: Array<string>,
|
||||
headers?: object,
|
||||
};
|
||||
|
||||
// isomorphic-git internally will default an empty ('') clone directory to '.'
|
||||
// Ref: https://github.com/isomorphic-git/isomorphic-git/blob/4e66704d05042624bbc78b85ee5110d5ee7ec3e2/src/utils/normalizePath.js#L10
|
||||
// We should set this explicitly (even if set to an empty string), because we have other code (such as fs plugins
|
||||
@ -60,6 +67,12 @@ export default class GitVCS {
|
||||
this._git = git;
|
||||
git.plugins.set('fs', fsPlugin);
|
||||
git.plugins.set('http', httpPlugin);
|
||||
const emitter = new EventEmitter();
|
||||
git.plugins.set('emitter', emitter);
|
||||
|
||||
emitter.on('message', message => {
|
||||
console.log(`[git-event] ${message}`);
|
||||
});
|
||||
|
||||
this._baseOpts = { dir: directory, gitdir: gitDirectory };
|
||||
|
||||
@ -229,11 +242,25 @@ export default class GitVCS {
|
||||
return true;
|
||||
}
|
||||
|
||||
async push(creds?: GitCredentials | null, force: boolean = false): Promise<boolean> {
|
||||
async push(creds?: GitCredentials | null, force: boolean = false): Promise<void> {
|
||||
console.log(`[git] Push remote=origin force=${force ? 'true' : 'false'}`);
|
||||
trackEvent('Git', 'Push');
|
||||
|
||||
return git.push({ ...this._baseOpts, remote: 'origin', ...creds, force });
|
||||
// eslint-disable-next-line no-unreachable
|
||||
const response: PushResponse = await git.push({
|
||||
...this._baseOpts,
|
||||
remote: 'origin',
|
||||
...creds,
|
||||
force,
|
||||
});
|
||||
|
||||
if (response.errors?.length) {
|
||||
console.log(`[git] Push rejected`, response);
|
||||
const errorsString = JSON.stringify(response.errors);
|
||||
throw new Error(
|
||||
`Push rejected with errors: ${errorsString}.\n\nGo to View > Toggle DevTools > Console for more information.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async pull(creds?: GitCredentials | null): Promise<void> {
|
||||
|
@ -77,7 +77,7 @@ type State = {
|
||||
|
||||
@autobind
|
||||
class GraphQLEditor extends React.PureComponent<Props, State> {
|
||||
_disabledOperationMarkers: TextMarker[];
|
||||
_disabledOperationMarkers: Array<TextMarker>;
|
||||
_documentAST: null | Object;
|
||||
_isMounted: boolean;
|
||||
_queryEditor: null | CodeMirror;
|
||||
|
@ -62,12 +62,12 @@ class ErrorModal extends PureComponent<{}, ErrorModalOptions> {
|
||||
<Modal ref={this._setModalRef}>
|
||||
<ModalHeader>{title || 'Uh Oh!'}</ModalHeader>
|
||||
<ModalBody className="wide pad">
|
||||
{message ? <div className="notice error">{message}</div> : null}
|
||||
{message ? <div className="notice error pre">{message}</div> : null}
|
||||
{error && (
|
||||
<details>
|
||||
<summary>Stack trace</summary>
|
||||
<pre className="pad-top-sm force-wrap selectable">
|
||||
<code>{error.stack || error}</code>
|
||||
<code className="wide">{error.stack || error}</code>
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
|
Loading…
Reference in New Issue
Block a user