Skip to content

Commit 35bb906

Browse files
Run test both from local binary and in docker. Use -d or --docker flag to run them in docker
1 parent 50e36f6 commit 35bb906

File tree

1 file changed

+179
-97
lines changed

1 file changed

+179
-97
lines changed

src/commands/test.js

Lines changed: 179 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { Binary } = require('binary-install-raw')
12
const os = require('os')
23
const chalk = require('chalk')
34
const fetch = require('node-fetch')
@@ -10,10 +11,12 @@ const HELP = `
1011
${chalk.bold('graph test')} ${chalk.dim('[options]')} ${chalk.bold('<datasource>')}
1112
1213
${chalk.dim('Options:')}
14+
-c, --coverage Run the tests in coverage mode. Works with v0.2.1 and above (0.2.2 and above in docker mode).
15+
-d, --docker Run the tests in a docker container
16+
-f --force Overwrite folder + file when downloading
1317
-h, --help Show usage information
18+
-l, --logs Logs to the console information about the OS, CPU model and download url (debugging purposes)
1419
-v, --version <tag> Choose the version of the rust binary that you want to be downloaded/used
15-
-c, --coverage Run tests in coverage mode (works with v0.2.2 and above)
16-
-f, --flags <flags>
1720
`
1821

1922
module.exports = {
@@ -23,20 +26,42 @@ module.exports = {
2326
let { print } = toolbox
2427

2528
// Read CLI parameters
26-
let { h, help, v, version, c, coverage } = toolbox.parameters.options
29+
let {
30+
c,
31+
coverage,
32+
d,
33+
docker,
34+
f,
35+
force,
36+
h,
37+
help,
38+
l,
39+
logs,
40+
v,
41+
version,
42+
} = toolbox.parameters.options
2743

2844
// Support both long and short option variants
45+
let coverage_opt = coverage || c
46+
let docker_opt = docker || d
47+
let force_opt = force || f
2948
let help_opt = help || h
49+
let logs_opt = logs || l
3050
let version_opt = version || v
31-
let coverage_opt = coverage || c
3251

33-
// Fix if a boolean flag (-h, --help, -c, --coverage) has an argument
52+
// Fix if a boolean flag (e.g -c, --coverage) has an argument
3453
try {
3554
fixParameters(toolbox.parameters, {
3655
h,
3756
help,
3857
c,
3958
coverage,
59+
d,
60+
docker,
61+
f,
62+
force,
63+
l,
64+
logs
4065
})
4166
} catch (e) {
4267
print.error(e.message)
@@ -52,117 +77,174 @@ module.exports = {
5277
return
5378
}
5479

55-
if(version_opt) {
56-
let url = `https://github.com/LimeChain/matchstick/releases/download/${version_opt || "0.2.2a"}/binary-linux-20`;
80+
if(docker_opt) {
81+
runDocker(coverage_opt, datasource, version_opt)
82+
} else {
83+
runBinary(coverage_opt, datasource, force_opt, logs_opt, version_opt)
84+
}
85+
}
86+
}
87+
88+
async function runBinary(coverage_opt, datasource, force_opt, logs_opt, version_opt) {
89+
const platform = getPlatform(logs_opt)
90+
91+
if (!version_opt) {
92+
let result = await fetch('https://api.github.com/repos/LimeChain/matchstick/releases/latest')
93+
let json = await result.json()
94+
version_opt = json.tag_name
95+
}
96+
97+
const url = `https://github.com/LimeChain/matchstick/releases/download/${version_opt}/${platform}`
98+
99+
if (logs_opt) {
100+
console.log(`Download link: ${url}`)
101+
}
57102

58-
await fetch(url)
59-
.then(response => {
60-
if (response.status === 404){
61-
print.info(`Error: Invalid Matchstick version '${version_opt}'`);
62-
process.exit(1);
63-
}
64-
})
103+
let binary = new Binary(platform, url, version_opt)
104+
force_opt ? await binary.install(true) : await binary.install(false)
105+
let args = ""
106+
107+
if (datasource) { args = datasource }
108+
if (coverage_opt) { args = args + ' -c' }
109+
args !== '' ? binary.run(args.trim()) : binary.run()
110+
}
111+
112+
function getPlatform(logs_opt) {
113+
const type = os.type()
114+
const arch = os.arch()
115+
const release = os.release()
116+
const cpuCore = os.cpus()[0]
117+
const majorVersion = semver.major(release)
118+
const isM1 = cpuCore.model.includes("Apple M1")
119+
120+
if (logs_opt) {
121+
console.log(`OS type: ${type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
122+
}
123+
124+
if (arch === 'x64' || (arch === 'arm64' && isM1)) {
125+
if (type === 'Darwin') {
126+
if (majorVersion === 19) {
127+
return 'binary-macos-10.15'
128+
} else if (majorVersion === 18) {
129+
return 'binary-macos-10.14'
130+
} else if (isM1) {
131+
return 'binary-macos-11-m1'
132+
}
133+
return 'binary-macos-11'
134+
} else if (type === 'Linux') {
135+
if (majorVersion === 18) {
136+
return 'binary-linux-18'
137+
}
138+
return 'binary-linux-20'
139+
} else if (type === 'Windows_NT') {
140+
return 'binary-windows'
65141
}
142+
}
66143

67-
// TODO: Move these in separate file (in a function maybe)
68-
let contents = `# I'll try to run it on alpine
69-
FROM ubuntu:20.04
144+
throw new Error(`Unsupported platform: ${type} ${arch} ${majorVersion}`)
145+
}
70146

71-
# Not sure if this ENV declaration is necessary
72-
ENV ARGS=""
147+
function runDocker(coverage_opt, datasource, version_opt) {
148+
fs.rmSync("node_modules/binary-install-raw/bin", { force: true, recursive: true });
73149

74-
# Install necessary packages
75-
RUN apt update
76-
RUN apt install -y nodejs
77-
RUN apt install -y npm
78-
RUN apt install -y git
79-
RUN apt install -y postgresql
80-
RUN apt install -y curl
81-
RUN npm install -g @graphprotocol/graph-cli
150+
let dir = 'tests/.docker';
82151

83-
# Download the latest linux binary
84-
RUN curl -OL https://github.com/LimeChain/matchstick/releases/download/${version_opt || "0.2.2a"}/binary-linux-20
85-
# Make it executable
86-
RUN chmod a+x binary-linux-20
152+
if (!fs.existsSync(dir)){
153+
fs.mkdirSync(dir, { recursive: true });
154+
}
87155

88-
# Create a matchstick dir where the host will be copied
89-
RUN mkdir matchstick
90-
WORKDIR matchstick
156+
fs.writeFileSync('tests/.docker/Dockerfile', dockerfile(version_opt), (err) => {
157+
if (err) {
158+
print.info('A problem occurred while generating the Dockerfile. Please attend to the errors below.');
159+
print.info(err);
160+
}
161+
else {
162+
print.info('Successfully generated Dockerfile.')
163+
}
164+
})
91165

92-
# Copy host to /matchstick
93-
COPY ../ .
166+
// Run a command to check if matchstick image already exists
167+
exec('docker images -q matchstick', (error, stdout, stderr) => {
168+
// Getting the current working folder that will be passed to the
169+
// `docker run` command to be bind mounted.
170+
let current_folder = process.cwd();
171+
let test_args = '';
94172

95-
RUN graph codegen
96-
RUN graph build
173+
if(datasource) {
174+
test_args = test_args + datasource
175+
}
97176

98-
CMD ../binary-linux-20 \${ARGS}
99-
`
177+
if(coverage_opt) {
178+
test_args = test_args + ' ' + '-c'
179+
}
100180

101-
let dir = 'tests/.docker';
181+
let docker_run_opts = ['run', '-it', '--rm', '--mount', `type=bind,source=${current_folder},target=/matchstick`];
102182

103-
if (!fs.existsSync(dir)){
104-
fs.mkdirSync(dir, { recursive: true });
183+
if(test_args !== '') {
184+
docker_run_opts.push('-e')
185+
docker_run_opts.push(`ARGS=${test_args.trim()}`);
105186
}
106187

107-
fs.writeFileSync('tests/.docker/Dockerfile', contents, (err) => {
108-
if (err) {
109-
print.info('A problem occurred while generating the Dockerfile. Please attend to the errors below.');
110-
print.info(err);
111-
}
112-
else {
113-
print.info('Successfully generated Dockerfile.')
188+
docker_run_opts.push('matchstick')
189+
190+
// If a matchstick image does not exists, the command returns an empty string,
191+
// else it'll return the image ID. Skip `docker build` if an image already exists
192+
// If `-v/--version` is specified, delete current image(if any) and rebuild.
193+
// Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
194+
if(stdout === '' || version_opt) {
195+
if (stdout !== '' && version_opt) {
196+
exec('docker image rm matchstick', (error, stdout, stderr) => {
197+
print.info(chalk.bold(`Removing matchstick image\n${stdout}`));
198+
});
114199
}
115-
})
200+
// Build a docker image. If the process has executed successfully
201+
// run a container from that image.
202+
spawn(
203+
'docker',
204+
['build', '-f', 'tests/.docker/Dockerfile', '-t', 'matchstick', '.'],
205+
{ stdio: 'inherit' }
206+
).on('close', code => {
207+
if (code === 0) {
208+
spawn('docker', docker_run_opts, { stdio: 'inherit' });
209+
}
210+
})
211+
} else {
212+
// Run the container from the existing matchstick docker image
213+
spawn('docker', docker_run_opts, { stdio: 'inherit' });
214+
}
215+
})
216+
}
116217

117-
// Run a command to check if matchstick image already exists
118-
exec('docker images -q matchstick', (error, stdout, stderr) => {
119-
// Getting the current working folder that will be passed to the
120-
// `docker run` command to be bind mounted.
121-
let current_folder = process.cwd();
122-
let test_args = '';
218+
// TODO: Move these in separate file (in a function maybe)
219+
function dockerfile(version_opt) {
220+
return `
221+
FROM ubuntu:20.04
222+
ENV ARGS=""
123223
124-
if(datasource) {
125-
test_args = test_args + datasource
126-
}
224+
# Install necessary packages
225+
RUN apt update
226+
RUN apt install -y nodejs
227+
RUN apt install -y npm
228+
RUN apt install -y git
229+
RUN apt install -y postgresql
230+
RUN apt install -y curl
231+
RUN npm install -g @graphprotocol/graph-cli
127232
128-
if(coverage_opt) {
129-
test_args = test_args + ' ' + '-c'
130-
}
233+
# Download the latest linux binary
234+
RUN curl -OL https://github.com/LimeChain/matchstick/releases/download/${version_opt || "0.2.2a"}/binary-linux-20
131235
132-
let docker_run_opts = ['run', '-it', '--rm', '--mount', `type=bind,source=${current_folder},target=/matchstick`];
236+
# Make it executable
237+
RUN chmod a+x binary-linux-20
133238
134-
if(test_args !== '') {
135-
docker_run_opts.push('-e')
136-
docker_run_opts.push(`ARGS=${test_args.trim()}`);
137-
}
239+
# Create a matchstick dir where the host will be copied
240+
RUN mkdir matchstick
241+
WORKDIR matchstick
138242
139-
docker_run_opts.push('matchstick')
140-
141-
// If a matchstick image does not exists, the command returns an empty string,
142-
// else it'll return the image ID. Skip `docker build` if an image already exists
143-
// If `-v/--version` is specified, delete current image(if any) and rebuild.
144-
// Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
145-
if(stdout === '' || version_opt) {
146-
if (stdout !== '' && version_opt) {
147-
exec('docker image rm matchstick', (error, stdout, stderr) => {
148-
print.info(chalk.bold(`Removing matchstick image\n${stdout}`));
149-
});
150-
}
151-
// Build a docker image. If the process has executed successfully
152-
// run a container from that image.
153-
spawn(
154-
'docker',
155-
['build', '-f', 'tests/.docker/Dockerfile', '-t', 'matchstick', '.'],
156-
{ stdio: 'inherit' }
157-
).on('close', code => {
158-
if (code === 0) {
159-
spawn('docker', docker_run_opts, { stdio: 'inherit' });
160-
}
161-
})
162-
} else {
163-
// Run the container from the existing matchstick docker image
164-
spawn('docker', docker_run_opts, { stdio: 'inherit' });
165-
}
166-
})
167-
},
243+
# Copy host to /matchstick
244+
COPY ../ .
245+
246+
RUN graph codegen
247+
RUN graph build
248+
249+
CMD ../binary-linux-20 \${ARGS}`
168250
}

0 commit comments

Comments
 (0)