1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 | 42x
42x
42x
42x
1x
1x
42x
6x
42x
12x
12x
12x
16x
12x
12x
12x
12x
12x
1x
11x
11x
42x
7x
42x
2x
1x
1x
1x
1x
1x
42x
4x
4x
3x
4x
3x
4x
4x
4x
4x
1x
1x
1x
42x
1x
1x
1x
42x
5x
3x
3x
3x
3x
2x
2x
2x
2x
42x
8x
8x
42x
| import { existsSync, chmodSync } from 'fs';
import { exec, spawn } from './process';
import LogModule = grunt.log.LogModule;
import { relative } from 'path';
export interface Options {
branch?: Publisher['branch'];
deployKey?: Publisher['deployKey'];
log?: Publisher['log'];
url?: Publisher['url'];
}
export interface Log {
writeln: LogModule['writeln'];
}
const consoleLogger = {
writeln(this: any, info: string) {
console.log(info);
return this;
}
};
export function setGlobalConfig(key: string, value: string) {
return exec(`git config --global ${ key } ${ value }`, { silent: true });
}
export default class Publisher {
/**
* The branch to publish
*/
branch: string = 'gh-pages';
/**
* The temporary directory for the local git clone
*/
cloneDirectory: string;
/**
* The deployment key to use
*/
deployKey: string = 'deploy_key';
/**
* Logging utility
*/
log: Log = consoleLogger;
/**
* The repo location
*/
url: string;
constructor(cloneDir: string, options: Options = {}) {
this.cloneDirectory = cloneDir;
// optional configuration values
options.branch && (this.branch = options.branch);
options.deployKey && (this.deployKey = options.deployKey);
options.log && (this.log = options.log);
if (options.url) {
this.url = options.url;
}
else {
const repo = process.env.TRAVIS_REPO_SLUG || ''; // TODO look up the repo information?
this.url = `git@github.com:${ repo }.git`;
}
}
/**
* @return {boolean} if a deploy key exists in the file system
*/
hasDeployCredentials(): boolean {
return existsSync(this.deployKey);
}
/**
* Commit files to a fresh clone of the repository
*/
commit(): boolean {
if (exec('git status --porcelain', { silent: true, cwd: this.cloneDirectory }) === '') {
this.log.writeln('Nothing changed');
return false;
}
exec(`git add --all .`, { silent: true, cwd: this.cloneDirectory });
exec('git commit -m "Update API docs"', { silent: true, cwd: this.cloneDirectory });
return true;
}
/**
* Initialize the repo and prepare for it to check in
*/
init() {
const publishBranch = this.branch;
// Prerequisites for using git
if (!this.hasConifg('user.name')) {
setGlobalConfig('user.name', 'Travis CI');
}
if (!this.hasConifg('user.email')) {
setGlobalConfig('user.email', 'support@sitepen.com');
}
this.log.writeln(`Cloning ${ this.url }`);
this.execSSHAgent('git', [ 'clone', this.url, this.cloneDirectory ], { silent: true });
try {
exec(`git checkout ${ publishBranch }`, { silent: true, cwd: this.cloneDirectory });
}
catch (error) {
// publish branch didn't exist, so create it
exec(`git checkout --orphan ${ publishBranch }`, { silent: true, cwd: this.cloneDirectory });
exec('git rm -rf .', { silent: true, cwd: this.cloneDirectory });
this.log.writeln(`Created ${publishBranch} branch`);
}
}
/**
* Publish the contents of { sourceDirectory } in the clone at { cloneDir } in the directory
* { subDirectory } and push to the { branch } branch.
*/
publish() {
this.log.writeln(`Publishing ${this.branch} to origin`);
this.execSSHAgent('git', [ 'push', 'origin', this.branch ], { silent: true, cwd: this.cloneDirectory });
this.log.writeln(`Pushed ${this.branch} to origin`);
}
/**
* Execute a credentialed git command
* @param command the command to execute
* @param options execute options
*/
private execSSHAgent(command: string, args: string[], options: any): string {
if (this.hasDeployCredentials()) {
const deployKey: string = <string> this.deployKey;
const relativeDeployKey = options.cwd ? relative(options.cwd, deployKey) : deployKey;
chmodSync(deployKey, '600');
return exec(`ssh-agent bash -c 'ssh-add ${ relativeDeployKey }; ${ command } ${ args.join(' ') }'`, options);
}
else {
this.log.writeln(`Deploy Key "${ this.deployKey }" is not present. Using environment credentials.`);
const response = spawn(command, args, options);
Iif (response.stderr) {
this.log.writeln(response.stderr);
}
return response.stdout;
}
}
private hasConifg(key: string): boolean {
try {
return !!exec(`git config ${ key }`, { silent: true });
}
catch (e) { }
return false;
}
}
|