Skip to content

Commit 2952bd3

Browse files
committed
Add all the code from our internal tooling for NodeJS and serving a static web page.
1 parent 246be85 commit 2952bd3

File tree

7 files changed

+354
-31
lines changed

7 files changed

+354
-31
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ apply from: 干.file('base/maven.gradle')
1313
apply from: 干.file('base/sonatype.gradle')
1414

1515
dependencies {
16+
// node.js
17+
api 'com.github.eirslett:frontend-maven-plugin:1.15.0' // JitPack HEAD as of 04/23/2020
1618
// static file server
1719
String VER_JETTY = '11.0.20'
1820
api "org.eclipse.jetty:jetty-server:$VER_JETTY"

gradle.properties

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@ org=diffplug
55
license=apache
66
git_url=github.com/diffplug/webtools
77
plugin_tags=node
8-
plugin_list=\
9-
node \
10-
servestatic
8+
plugin_list=node
119

12-
ver_java=17
10+
ver_java=11
1311

1412
javadoc_links=
1513

16-
plugin_node_id=com.diffplug.eclipse.apt
17-
plugin_node_impl=com.diffplug.gradle.eclipse.apt.AptEclipsePlugin
18-
plugin_node_name=Copy of net.ltgt.apt-eclipse which is still maintained
19-
plugin_node_desc=Fixes eclipse projects to work with gradle annotation processing
20-
21-
plugin_servestatic_id=com.diffplug.eclipse.buildproperties
22-
plugin_servestatic_impl=com.diffplug.gradle.eclipse.BuildPropertiesPlugin
23-
plugin_servestatic_name=Goomph servestatic
24-
plugin_servestatic_desc=Uses Eclipse''s build.properties to control a gradle build, and fixes the eclipse project classpath to include binary assets specified in build.properties.
14+
plugin_node_id=com.diffplug.webtools.node
15+
plugin_node_impl=com.diffplug.webtools.node.NodePlugin
16+
plugin_node_name=DiffPlug NodeJS
17+
plugin_node_desc=Runs `npm install` and `npm run xx` in an efficient way

src/main/java/com/diffplug/gradle/CmdLine.java

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (C) 2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.webtools.node;
17+
18+
import com.github.eirslett.maven.plugins.frontend.lib.ProxyConfig;
19+
import java.util.Collections;
20+
import java.util.Objects;
21+
import org.gradle.api.Action;
22+
import org.gradle.api.DefaultTask;
23+
import org.gradle.api.Plugin;
24+
import org.gradle.api.Project;
25+
import org.gradle.api.Task;
26+
import org.gradle.api.file.DirectoryProperty;
27+
import org.gradle.api.provider.Property;
28+
import org.gradle.api.tasks.CacheableTask;
29+
import org.gradle.api.tasks.Input;
30+
import org.gradle.api.tasks.Internal;
31+
import org.gradle.api.tasks.PathSensitivity;
32+
import org.gradle.api.tasks.TaskAction;
33+
import org.gradle.api.tasks.TaskProvider;
34+
35+
/**
36+
* Installs a specific version of node.js and npm,
37+
* Runs 'npm ci' to install the packages, and then `gulp blah`
38+
* to run whatever gulp tasks you want.
39+
*/
40+
public class NodePlugin implements Plugin<Project> {
41+
private static final String EXTENSION_NAME = "node";
42+
43+
public static class Extension {
44+
private final Project project;
45+
46+
public Extension(Project project) {
47+
this.project = Objects.requireNonNull(project);
48+
}
49+
50+
public final SetupCleanupNode setup = new SetupCleanupNode();
51+
52+
public TaskProvider<?> npm_run(String name, Action<Task> taskConfig) {
53+
return project.getTasks().register("npm_run_" + name, NpmRunTask.class, task -> {
54+
task.taskName = name;
55+
task.getSetup().set(setup);
56+
task.getProjectDir().set(project.getProjectDir());
57+
task.getInputs().file("package-lock.json").withPathSensitivity(PathSensitivity.RELATIVE);
58+
59+
task.getInputs().property("nodeVersion", setup.nodeVersion);
60+
task.getInputs().property("npmVersion", setup.npmVersion);
61+
taskConfig.execute(task);
62+
});
63+
}
64+
}
65+
66+
@CacheableTask
67+
public abstract static class NpmRunTask extends DefaultTask {
68+
public String taskName;
69+
70+
@Input
71+
public String getTaskName() {
72+
return taskName;
73+
}
74+
75+
@Internal
76+
public abstract Property<SetupCleanupNode> getSetup();
77+
78+
@Internal
79+
public abstract DirectoryProperty getProjectDir();
80+
81+
@TaskAction
82+
public void npmCiRunTask() throws Exception {
83+
SetupCleanupNode setup = getSetup().get();
84+
// install node, npm, and package-lock.json
85+
setup.start(getProjectDir().get().getAsFile());
86+
// run the gulp task
87+
ProxyConfig proxyConfig = new ProxyConfig(Collections.emptyList());
88+
setup.factory().getNpmRunner(proxyConfig, null).execute("run " + taskName, null);
89+
}
90+
}
91+
92+
@Override
93+
public void apply(Project project) {
94+
extension = project.getExtensions().create(EXTENSION_NAME, Extension.class, project);
95+
}
96+
97+
private Extension extension;
98+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (C) 2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.webtools.node;
17+
18+
import java.io.ByteArrayInputStream;
19+
import java.io.ByteArrayOutputStream;
20+
import java.io.File;
21+
import java.io.IOException;
22+
import java.io.ObjectInputStream;
23+
import java.io.ObjectOutputStream;
24+
import java.nio.file.Files;
25+
import java.util.Arrays;
26+
27+
abstract class SetupCleanup<K> {
28+
public void start(File keyFile, K key) throws Exception {
29+
byte[] required = toBytes(key);
30+
if (keyFile.exists()) {
31+
byte[] actual = Files.readAllBytes(keyFile.toPath());
32+
if (Arrays.equals(actual, required)) {
33+
// short-circuit if our state is already setup
34+
return;
35+
} else {
36+
Files.delete(keyFile.toPath());
37+
@SuppressWarnings("unchecked")
38+
K lastKey = (K) fromBytes(required);
39+
doStop(lastKey);
40+
}
41+
}
42+
// write out the key
43+
doStart(key);
44+
Files.createDirectories(keyFile.toPath().getParent());
45+
Files.write(keyFile.toPath(), required);
46+
}
47+
48+
protected abstract void doStart(K key) throws Exception;
49+
50+
protected abstract void doStop(K key) throws Exception;
51+
52+
private static byte[] toBytes(Object key) {
53+
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
54+
try (ObjectOutputStream objectOutput = new ObjectOutputStream(bytes)) {
55+
objectOutput.writeObject(key);
56+
} catch (IOException e) {
57+
throw new RuntimeException(e);
58+
}
59+
return bytes.toByteArray();
60+
}
61+
62+
private static Object fromBytes(byte[] raw) throws ClassNotFoundException {
63+
ByteArrayInputStream bytes = new ByteArrayInputStream(raw);
64+
try (ObjectInputStream objectOutput = new ObjectInputStream(bytes)) {
65+
return objectOutput.readObject();
66+
} catch (IOException e) {
67+
throw new RuntimeException(e);
68+
}
69+
}
70+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (C) 2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.webtools.node;
17+
18+
import com.github.eirslett.maven.plugins.frontend.lib.FrontendPluginFactory;
19+
import com.github.eirslett.maven.plugins.frontend.lib.InstallationException;
20+
import com.github.eirslett.maven.plugins.frontend.lib.ProxyConfig;
21+
import com.github.eirslett.maven.plugins.frontend.lib.TaskRunnerException;
22+
import java.io.File;
23+
import java.io.Serializable;
24+
import java.nio.file.Files;
25+
import java.util.Collections;
26+
27+
class SetupCleanupNode implements Serializable {
28+
public String nodeVersion;
29+
public String npmVersion;
30+
private File workingDir, installDir;
31+
@SuppressWarnings("unused") // used for serialized equality
32+
private byte[] packageLockJson;
33+
34+
public void start(File projectDir) throws Exception {
35+
workingDir = projectDir;
36+
installDir = new File(projectDir, "build/node-install");
37+
packageLockJson = Files.readAllBytes(workingDir.toPath().resolve("package-lock.json"));
38+
new Impl().start(keyFile(projectDir), this);
39+
}
40+
41+
FrontendPluginFactory factory() {
42+
return new FrontendPluginFactory(workingDir, installDir);
43+
}
44+
45+
private static File keyFile(File projectDir) {
46+
return new File(projectDir, "build/node_modules/.gradle-state");
47+
}
48+
49+
private static class Impl extends SetupCleanup<SetupCleanupNode> {
50+
@Override
51+
protected void doStart(SetupCleanupNode key) throws TaskRunnerException, InstallationException {
52+
ProxyConfig proxyConfig = new ProxyConfig(Collections.emptyList());
53+
FrontendPluginFactory factory = key.factory();
54+
factory.getNodeInstaller(proxyConfig)
55+
.setNodeVersion(key.nodeVersion)
56+
.setNpmVersion(key.npmVersion)
57+
.install();
58+
factory.getNpmRunner(proxyConfig, null)
59+
.execute("ci", null);
60+
}
61+
62+
@Override
63+
protected void doStop(SetupCleanupNode key) throws Exception {
64+
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)