Skip to content

Commit 066e90b

Browse files
authored
feat(up): checkout and use helix-pages if no source scripts are present (#946)
fixes #929
1 parent a722e57 commit 066e90b

File tree

10 files changed

+304
-7
lines changed

10 files changed

+304
-7
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ logs/*
33
demos/*
44
test/integration
55
test/integration-with-cgi-bin
6+
test/fixtures/helix-pages
67
test/tmp/*
78
tmp/*
89
coverage/*

src/helix-pages.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2019 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
const path = require('path');
13+
const fse = require('fs-extra');
14+
const shell = require('shelljs');
15+
const { GitUrl } = require('@adobe/helix-shared');
16+
17+
function execAsync(cmd) {
18+
return new Promise((resolve, reject) => {
19+
shell.exec(cmd, (code, stdout, stderr) => {
20+
if (code === 0) {
21+
resolve(0);
22+
} else {
23+
reject(stderr);
24+
}
25+
});
26+
});
27+
}
28+
29+
/**
30+
* Utilities for helix pages
31+
*/
32+
class HelixPages {
33+
constructor(logger) {
34+
this._logger = logger;
35+
this._cwd = process.cwd();
36+
this._repo = 'https://github.com/adobe/helix-pages.git';
37+
this._ref = 'master';
38+
}
39+
40+
withDirectory(value) {
41+
this._cwd = value;
42+
return this;
43+
}
44+
45+
withRepo(value) {
46+
this._repo = value;
47+
}
48+
49+
get log() {
50+
return this._logger;
51+
}
52+
53+
get directory() {
54+
return this._cwd;
55+
}
56+
57+
get homeDirectory() {
58+
return this._homeDirectory;
59+
}
60+
61+
get srcDirectory() {
62+
return this._srcDirectory;
63+
}
64+
65+
get checkoutDirectory() {
66+
return this._checkoutDir;
67+
}
68+
69+
get staticURL() {
70+
return this._staticURL;
71+
}
72+
73+
async isPagesProject() {
74+
return !await fse.pathExists(path.join(this.directory, 'src'));
75+
}
76+
77+
async init() {
78+
// check if helix-pages checkout exists
79+
// todo: add support to check for updates and version control
80+
this._homeDirectory = path.resolve(this.directory, '.hlx', 'pages');
81+
this._checkoutDir = path.resolve(this.homeDirectory, this._ref);
82+
this._srcDirectory = path.resolve(this.checkoutDirectory, 'src');
83+
this._staticURL = new GitUrl('https://github.com/adobe/helix-pages.git/htdocs');
84+
85+
if (!await fse.pathExists(this.checkoutDirectory)) {
86+
this.log.info(`Checking out sources from ${this._repo}#${this._ref}`);
87+
try {
88+
await execAsync(`git clone --branch ${this._ref} --quiet --depth 1 ${this._repo} ${this.checkoutDirectory}`);
89+
} catch (e) {
90+
throw Error(`Unable to checkout helix-pages repository: ${e}`);
91+
}
92+
}
93+
}
94+
}
95+
96+
module.exports = HelixPages;

src/up.cmd.js

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const { HelixProject } = require('@adobe/helix-simulator');
2020
const GitUtils = require('./git-utils.js');
2121
const BuildCommand = require('./build.cmd');
2222
const pkgJson = require('../package.json');
23+
const HelixPages = require('./helix-pages.js');
2324

2425
const HELIX_CONFIG = 'helix-config.yaml';
2526

@@ -31,6 +32,7 @@ class UpCommand extends BuildCommand {
3132
this._saveConfig = false;
3233
this._overrideHost = null;
3334
this._localRepos = [];
35+
this._helixPagesRepo = '';
3436
}
3537

3638
withHttpPort(p) {
@@ -62,6 +64,11 @@ class UpCommand extends BuildCommand {
6264
return this;
6365
}
6466

67+
withHelixPagesRepo(url) {
68+
this._helixPagesRepo = url;
69+
return this;
70+
}
71+
6572
get project() {
6673
return this._project;
6774
}
@@ -162,19 +169,58 @@ class UpCommand extends BuildCommand {
162169
};
163170
}));
164171

165-
// start debugger (#178)
166-
// https://nodejs.org/en/docs/guides/debugging-getting-started/#enable-inspector
167-
if (process.platform !== 'win32') {
168-
process.kill(process.pid, 'SIGUSR1');
169-
}
170-
171172
this._project = new HelixProject()
172173
.withCwd(this.directory)
173174
.withBuildDir(this._target)
174175
.withHelixConfig(this.config)
175-
.withDisplayVersion(pkgJson.version)
176176
.withRuntimeModulePaths(module.paths);
177177

178+
// special handling for helix pages project
179+
const pages = new HelixPages(this._logger).withDirectory(this.directory);
180+
if (await pages.isPagesProject()) {
181+
this.log.info(' __ __ ___ ___ ');
182+
this.log.info(' / // /__ / (_)_ __ / _ \\___ ____ ____ ___');
183+
this.log.info(' / _ / -_) / /\\ \\ // ___/ _ `/ _ `/ -_|_-<');
184+
this.log.info(' /_//_/\\__/_/_//_\\_\\/_/ \\_,_/\\_, /\\__/___/');
185+
this.log.info(` /___/ v${pkgJson.version}`);
186+
this.log.info('');
187+
188+
if (this._helixPagesRepo) {
189+
pages.withRepo(this._helixPagesRepo);
190+
}
191+
192+
await pages.init();
193+
194+
// use bundled helix-pages sources
195+
this.withFiles([`${pages.srcDirectory}/**/*.htl`, `${pages.srcDirectory}/**/*.js`]);
196+
this._project.withSourceDir(pages.srcDirectory);
197+
198+
// use bundled helix-pages htdocs
199+
if (!await fse.pathExists(path.join(this.directory, 'htdocs'))) {
200+
this.config.strains.get('default').static.url = pages.staticURL;
201+
localRepos.push({
202+
repoPath: pages.checkoutDirectory,
203+
gitUrl: pages.staticURL,
204+
});
205+
this.config.strains.get('default').static.url = pages.staticURL;
206+
}
207+
208+
// pretend to have config file to suppress message below
209+
hasConfigFile = true;
210+
} else {
211+
this.log.info(' __ __ ___ ');
212+
this.log.info(' / // /__ / (_)_ __ ');
213+
this.log.info(' / _ / -_) / /\\ \\ / ');
214+
this.log.info(` /_//_/\\__/_/_//_\\_\\ v${pkgJson.version}`);
215+
this.log.info(' ');
216+
}
217+
218+
// start debugger (#178)
219+
// https://nodejs.org/en/docs/guides/debugging-getting-started/#enable-inspector
220+
if (process.platform !== 'win32') {
221+
process.kill(process.pid, 'SIGUSR1');
222+
}
223+
178224
if (this._httpPort >= 0) {
179225
this._project.withHttpPort(this._httpPort);
180226
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
minimal checkout of helix pages for testing
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2018 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
body {
14+
padding: 0;
15+
margin: 0;
16+
background-color: white;
17+
font-family: "source-sans-pro", sans-serif;
18+
font-size: 1rem;
19+
font-weight: 300;
20+
line-height: 1.5;
21+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>${content.title}</title>
5+
</head>
6+
<body>
7+
${content.document.body.innerHTML}
8+
</body>
9+
</html>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
/**
20+
* The 'pre' function that is executed before the HTML is rendered
21+
* @param context The current context of processing pipeline
22+
* @param context.content The content
23+
*/
24+
function pre(context) {
25+
}
26+
27+
module.exports.pre = pre;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
template: homepage
3+
---
4+
5+
# Soup Demo Test
6+
7+
This is rendered using ~~Sightly~~ HTL.
8+
9+
> [!NOTE]
10+
> This is a note. Who'd have noted?
11+
12+
{% jekyll_embed with params %}

test/specs/pages_response.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<html><head><title>Soup Demo Test</title></head><body><h1 id="soup-demo-test">Soup Demo Test</h1><p>This is rendered using <del>Sightly</del> HTL.</p><blockquote><p>[!NOTE] This is a note. Who’d have noted?</p></blockquote><p>{% jekyll_embed with params %}</p></body></html>

test/testUpCmdPages.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2019 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
/* eslint-env mocha */
14+
const path = require('path');
15+
const fse = require('fs-extra');
16+
17+
const {
18+
initGit,
19+
assertHttp,
20+
assertHttpDom,
21+
createTestRoot,
22+
} = require('./utils.js');
23+
24+
const UpCommand = require('../src/up.cmd');
25+
26+
const TEST_DIR = path.resolve('test/integration-helix-pages');
27+
28+
describe('Integration test for up command with helix pages', function suite() {
29+
this.timeout(20000);
30+
let testDir;
31+
let buildDir;
32+
let testRoot;
33+
let helixPagesRepo;
34+
35+
beforeEach(async () => {
36+
testRoot = await createTestRoot();
37+
testDir = path.resolve(testRoot, 'project');
38+
buildDir = path.resolve(testDir, '.hlx/build');
39+
helixPagesRepo = path.resolve(testRoot, 'helix-pages');
40+
await fse.copy(TEST_DIR, testDir);
41+
42+
// init helix-pages fake local repo. we do this, because we don't want git checkouts in
43+
// the helix-cli repository, and we want to keep the tests offline
44+
await fse.copy(path.resolve(__dirname, 'fixtures', 'helix-pages', 'master'), helixPagesRepo);
45+
initGit(helixPagesRepo, 'https://github.com/adobe/helix-pages.git');
46+
});
47+
48+
afterEach(async () => {
49+
// await fse.remove(testRoot);
50+
});
51+
52+
it('up command delivers correct response.', (done) => {
53+
initGit(testDir, 'https://github.com/adobe/dummy-foo.git');
54+
let error = null;
55+
const cmd = new UpCommand()
56+
.withCacheEnabled(false)
57+
.withTargetDir(buildDir)
58+
.withDirectory(testDir)
59+
.withHelixPagesRepo(helixPagesRepo)
60+
.withHttpPort(0);
61+
62+
const myDone = (err) => {
63+
error = err;
64+
return cmd.stop();
65+
};
66+
67+
cmd
68+
.on('started', async () => {
69+
try {
70+
await assertHttpDom(`http://localhost:${cmd.project.server.port}/index.html`, 200, 'pages_response.html');
71+
await assertHttp(`http://localhost:${cmd.project.server.port}/style.css`, 200, path.resolve(helixPagesRepo, 'htdocs', 'style.css'));
72+
myDone();
73+
} catch (e) {
74+
myDone(e);
75+
}
76+
})
77+
.on('stopped', () => {
78+
done(error);
79+
})
80+
.run()
81+
.catch(done);
82+
});
83+
});

0 commit comments

Comments
 (0)