Support serving demos from a dedicated directory, and add script for populating that directory from a repo.
Change-Id: I9d961a6e7f05e1af1ec8239370ac41b2bca73131
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/285659
Commit-Queue: Weston Tracey <westont@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/demos/.gitignore b/demos/.gitignore
new file mode 100644
index 0000000..f5a6742
--- /dev/null
+++ b/demos/.gitignore
@@ -0,0 +1,2 @@
+fetched_demos/
+build/
diff --git a/demos/Dockerfile b/demos/Dockerfile
index 820c7d6..1beed27 100644
--- a/demos/Dockerfile
+++ b/demos/Dockerfile
@@ -5,5 +5,7 @@
USER skia
ENTRYPOINT ["/usr/local/bin/demoserver"]
-CMD ["--logtostderr", "--port=:8000", "--resources_dir=/usr/local/share/demoserver/"]
+CMD ["--logtostderr", "--port=:8000", \
+ "--resources_dir=/usr/local/share/demoserver/dist", \
+ "--demos_dir=/usr/local/share/demoserver/demos"]
diff --git a/demos/Makefile b/demos/Makefile
index 5841aa1..7da3a9e 100644
--- a/demos/Makefile
+++ b/demos/Makefile
@@ -4,12 +4,38 @@
serve:
npx webpack-dev-server --watch-poll --mode-development
-build_resources:
+fetch_demos:
+ go run ./go/load-demo-assets/main.go \
+ --alsologtostderr \
+ --demos_dir "demos/internal" \
+ --out_dir "fetched_demos" \
+ --repo_url "https://skia.googlesource.com/infra-internal"
+
+wasm_libs:
+ rm -rf build
+ mkdir -p build/canvaskit build/pathkit
+ # Extract them from the most recently built ones.
+ # Run as current user so they have non-root ownership.
+ docker run -u $$(id -u ${USER}):$$(id -g ${USER}) --rm \
+ --volume `pwd`/build:/OUT gcr.io/skia-public/skia-wasm-release:prod \
+ sh -c "cp -r /tmp/* /OUT/"
+ echo "export const SKIA_VERSION = '`cat build/VERSION`';" > build/version.js
+
+build_resources: wasm_libs
npx webpack --mode=production
run: build_resources core
- demoserver --alsologtostderr
+ demoserver \
+ --alsologtostderr \
+ --port=:8000 \
+ --resources_dir="dist" \
+ --demos_dir="fetched_demos"
-release: build_resources
+
+release: build_resources fetch_demos
CGO_ENABLED=0 GOOS=linux go install -a ./go/demoserver
./build_release
+
+local_image: build_resources fetch_demos
+ CGO_ENABLED=0 GOOS=linux go install -a ./go/demoserver
+ SKIP_UPLOAD=1 ./build_release
diff --git a/demos/build_release b/demos/build_release
index 71dae5e..af86384 100755
--- a/demos/build_release
+++ b/demos/build_release
@@ -8,10 +8,14 @@
{
INSTALL="install -D --verbose --backup=none"
INSTALL_DIR="install -d --verbose --backup=none"
-${INSTALL} --mode=644 -T Dockerfile ${ROOT}/Dockerfile
-${INSTALL} --mode=755 -T ${GOPATH}/bin/${APPNAME} ${ROOT}/usr/local/bin/${APPNAME}
-${INSTALL_DIR} --mode=755 ${ROOT}/usr/local/share/${APPNAME}/
-${INSTALL} --mode=644 ./dist/* ${ROOT}/usr/local/share/${APPNAME}/
+${INSTALL} --mode=644 -T Dockerfile ${ROOT}/Dockerfile
+${INSTALL} --mode=755 -T ${GOPATH}/bin/${APPNAME} ${ROOT}/usr/local/bin/${APPNAME}
+# Resources for the main page.
+${INSTALL_DIR} --mode=755 ${ROOT}/usr/local/share/${APPNAME}/
+${INSTALL} --mode=755 ./dist/* ${ROOT}/usr/local/share/${APPNAME}/
+# Demo pages. 'install' isn't recursive.
+cp -r ./fetched_demos ${ROOT}/usr/local/share/${APPNAME}/demos
+chmod -R a=rX,u=rwX ${ROOT}/usr/local/share/${APPNAME}/demos
}
source ../bash/docker_build.sh
diff --git a/demos/go/demoserver/main.go b/demos/go/demoserver/main.go
index 8b9b125..c1e398c 100644
--- a/demos/go/demoserver/main.go
+++ b/demos/go/demoserver/main.go
@@ -1,6 +1,6 @@
package main
-// The webserver for demos.skia.org. It serves the main page to navigate among JS demos.
+// The webserver for demos.skia.org. It serves a main page and a set of js+html+css demos.
import (
"flag"
@@ -15,6 +15,7 @@
var (
port = flag.String("port", ":8000", "HTTP service address (e.g., ':8000')")
+ demosDir = flag.String("demos_dir", "./demos/public", "The directory to find named subdirectories for each demo. If blank ./demos/public")
resourcesDir = flag.String("resources_dir", "./dist", "The directory to find templates, JS, and CSS files. If blank ./dist will be used.")
)
@@ -22,7 +23,12 @@
common.InitWithMust(
"demos",
)
+
r := mux.NewRouter()
+ r.PathPrefix("/demo/").Handler(http.StripPrefix("/demo", http.FileServer(http.Dir(*demosDir))))
+ // PathPrefix above needs a slash to make FileServer relative paths work.
+ // For cleanliness, make sure users get to the directory listing even without the slash.
+ r.Handle("/demo", http.RedirectHandler("/demo/", 301))
r.PathPrefix("/dist/").Handler(http.StripPrefix("/dist/", http.FileServer(http.Dir(*resourcesDir))))
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filepath.Join(*resourcesDir, "main.html"))
diff --git a/demos/go/load-demo-assets/main.go b/demos/go/load-demo-assets/main.go
new file mode 100644
index 0000000..c5037d1
--- /dev/null
+++ b/demos/go/load-demo-assets/main.go
@@ -0,0 +1,45 @@
+package main
+
+// Loads all checked in demos from infra-internal to be bundled into the demoserver image for
+// release.
+
+import (
+ "context"
+ "flag"
+ "path/filepath"
+
+ "go.skia.org/infra/go/auth"
+ "go.skia.org/infra/go/gitiles"
+ "go.skia.org/infra/go/httputils"
+
+ "go.skia.org/infra/go/sklog"
+)
+
+var (
+ demosRepo = flag.String("repo_url", "https://skia.googlesource.com/infra-internal", "The repo from where to fetch the demos. Defaults to https://skia.googlesource.com/infra-internal")
+ demosRepoPath = flag.String("demos_dir", "scripts", "The top level directory in the repo that holds the demos.")
+ outDir = flag.String("out_dir", "./out", "Where the demos from demos_dir should be downloaded to, directories will be created as needed.")
+)
+
+func main() {
+ flag.Parse()
+ ts, err := auth.NewDefaultTokenSource(true, auth.SCOPE_USERINFO_EMAIL, auth.SCOPE_GERRIT)
+ if err != nil {
+ sklog.Fatal(err)
+ }
+ client := httputils.DefaultClientConfig().WithTokenSource(ts).Client()
+ repo := gitiles.NewRepo(*demosRepo, client)
+ files, err := repo.ListFilesRecursive(context.Background(), *demosRepoPath)
+ if err != nil {
+ sklog.Fatal(err)
+ }
+ sklog.Infof("Downloading files: %v", files)
+
+ for _, f := range files {
+ err := repo.DownloadFile(context.Background(), filepath.Join(*demosRepoPath, f), filepath.Join(*outDir, f))
+ if err != nil {
+ sklog.Fatal(err)
+ }
+ }
+
+}
diff --git a/demos/package-lock.json b/demos/package-lock.json
index 4420325..8901e44 100644
--- a/demos/package-lock.json
+++ b/demos/package-lock.json
@@ -1,5 +1,5 @@
{
- "name": "ctfe",
+ "name": "demos",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
@@ -2495,6 +2495,108 @@
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
},
+ "copy-webpack-plugin": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz",
+ "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==",
+ "dev": true,
+ "requires": {
+ "cacache": "^10.0.4",
+ "find-cache-dir": "^1.0.0",
+ "globby": "^7.1.1",
+ "is-glob": "^4.0.0",
+ "loader-utils": "^1.1.0",
+ "minimatch": "^3.0.4",
+ "p-limit": "^1.0.0",
+ "serialize-javascript": "^1.4.0"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+ "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.1",
+ "chownr": "^1.0.1",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.2",
+ "ssri": "^5.2.4",
+ "unique-filename": "^1.1.0",
+ "y18n": "^4.0.0"
+ }
+ },
+ "globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ }
+ },
+ "mississippi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+ "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^2.0.1",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "serialize-javascript": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
+ "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
+ "dev": true
+ },
+ "ssri": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+ "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ }
+ }
+ },
"core-js": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
@@ -3136,6 +3238,26 @@
"randombytes": "^2.0.0"
}
},
+ "dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "dev": true,
+ "requires": {
+ "path-type": "^3.0.0"
+ },
+ "dependencies": {
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ }
+ }
+ },
"dns-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -5629,6 +5751,12 @@
"resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
"integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
},
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+ "dev": true
+ },
"import-cwd": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
diff --git a/demos/package.json b/demos/package.json
index 33d3400..227084d 100644
--- a/demos/package.json
+++ b/demos/package.json
@@ -13,6 +13,7 @@
"autoprefixer": "^9.7.4",
"bower": "^1.8.8",
"chai": "~4.2.0",
+ "copy-webpack-plugin": "^4.6.0",
"cssmin": "~0.4.2",
"fetch-mock": "~7.3.9",
"html-minifier": "~3.0.0",
diff --git a/demos/webpack.config.js b/demos/webpack.config.js
index 9ccae9e..80e4fad 100644
--- a/demos/webpack.config.js
+++ b/demos/webpack.config.js
@@ -1,5 +1,6 @@
const commonBuilder = require('pulito');
-const {resolve} = require('path');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+const { resolve } = require('path');
module.exports = (env, argv) => {
const config = commonBuilder(env, argv, __dirname);
@@ -7,6 +8,16 @@
config.resolve = config.resolve || {};
// https://github.com/webpack/node-libs-browser/issues/26#issuecomment-267954095
config.resolve.modules = [resolve(__dirname, 'node_modules'), 'node_modules'];
+ config.plugins.push(
+ new CopyWebpackPlugin([
+ { from: resolve(__dirname, 'build/canvaskit/canvaskit.wasm') },
+ { from: resolve(__dirname, 'build/canvaskit/canvaskit.js') },
+ { from: resolve(__dirname, 'node_modules/@webcomponents/custom-elements/custom-elements.min.js') },
+ ]),
+ );
+ config.node = {
+ fs: 'empty',
+ };
return config;
-}
+};
diff --git a/go/util/util.go b/go/util/util.go
index a2c6310..7ec3d55 100644
--- a/go/util/util.go
+++ b/go/util/util.go
@@ -622,7 +622,11 @@
// temporary intermediate file for more atomicity in case a long-running write
// gets interrupted.
func WithWriteFile(file string, writeFn func(io.Writer) error) error {
- f, err := ioutil.TempFile(path.Dir(file), path.Base(file))
+ dir := path.Dir(file)
+ if err := os.MkdirAll(dir, 700); err != nil {
+ return fmt.Errorf("Failed to MkdirAll(%s, 700): %v", dir, err)
+ }
+ f, err := ioutil.TempFile(dir, path.Base(file))
if err != nil {
return fmt.Errorf("Failed to create temporary file for WithWriteFile: %s", err)
}