Merge pull request #4952 from penpot/ladybenko-8439-storybook-build

Storybook build
This commit is contained in:
Andrey Antukh 2024-08-06 10:25:18 +02:00 committed by GitHub
commit d0059cbe29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 188 additions and 32 deletions

View file

@ -22,10 +22,10 @@ jobs:
# Download and cache dependencies # Download and cache dependencies
- restore_cache: - restore_cache:
keys: keys:
- v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}} - v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}}
# fallback to using the latest cache if no exact match is found # fallback to using the latest cache if no exact match is found
- v1-dependencies- - v1-dependencies-
- run: cd .clj-kondo && cat config.edn - run: cd .clj-kondo && cat config.edn
- run: cat .cljfmt.edn - run: cat .cljfmt.edn
@ -108,7 +108,7 @@ jobs:
working_directory: "./frontend" working_directory: "./frontend"
command: | command: |
yarn install yarn install
yarn run compile yarn run build:app:assets
clojure -M:dev:shadow-cljs release main clojure -M:dev:shadow-cljs release main
yarn playwright install --with-deps chromium yarn playwright install --with-deps chromium
yarn e2e:test yarn e2e:test
@ -126,7 +126,6 @@ jobs:
PENPOT_TEST_REDIS_URI: "redis://localhost/1" PENPOT_TEST_REDIS_URI: "redis://localhost/1"
- save_cache: - save_cache:
paths: paths:
- ~/.m2 - ~/.m2
key: v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}} key: v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}}

3
.gitignore vendored
View file

@ -48,6 +48,8 @@
/deploy /deploy
/docker/images/bundle* /docker/images/bundle*
/exporter/target /exporter/target
/frontend/.storybook/preview-body.html
/frontend/.storybook/preview-head.html
/frontend/cypress/fixtures/validuser.json /frontend/cypress/fixtures/validuser.json
/frontend/cypress/videos/*/ /frontend/cypress/videos/*/
/frontend/cypress/videos/*/ /frontend/cypress/videos/*/
@ -68,7 +70,6 @@
/web /web
clj-profiler/ clj-profiler/
node_modules node_modules
frontend/.storybook/preview-body.html
/test-results/ /test-results/
/playwright-report/ /playwright-report/
/blob-report/ /blob-report/

View file

@ -149,6 +149,11 @@ http {
proxy_pass http://127.0.0.1:6060/ws/notifications; proxy_pass http://127.0.0.1:6060/ws/notifications;
} }
location /storybook {
alias /home/penpot/penpot/frontend/storybook-static/;
autoindex on;
}
location / { location / {
location ~ ^/github/penpot-files/(?<template_file>[a-zA-Z0-9\-\_\.]+) { location ~ ^/github/penpot-files/(?<template_file>[a-zA-Z0-9\-\_\.]+) {
proxy_pass https://raw.githubusercontent.com/penpot/penpot-files/main/$template_file; proxy_pass https://raw.githubusercontent.com/penpot/penpot-files/main/$template_file;

View file

@ -17,28 +17,28 @@
"@vitejs/plugin-react": "^4.2.0" "@vitejs/plugin-react": "^4.2.0"
}, },
"scripts": { "scripts": {
"fmt:clj:check": "cljfmt check --parallel=false src/ test/", "build:app:assets": "node ./scripts/build-app-assets.js",
"build:storybook": "yarn run build:storybook:assets && yarn run build:storybook:cljs && storybook build",
"build:storybook:assets": "node ./scripts/build-storybook-assets.js",
"build:storybook:cljs": "clojure -M:dev:shadow-cljs release storybook",
"e2e:server": "node ./scripts/e2e-server.js",
"e2e:test": "playwright test --project default",
"fmt:clj": "cljfmt fix --parallel=true src/ test/", "fmt:clj": "cljfmt fix --parallel=true src/ test/",
"fmt:js:check": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js", "fmt:clj:check": "cljfmt check --parallel=false src/ test/",
"fmt:js": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -w", "fmt:js": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -w",
"fmt:js:check": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js",
"lint:clj": "clj-kondo --parallel --lint src/",
"lint:scss": "yarn run prettier -c resources/styles -c src/**/*.scss", "lint:scss": "yarn run prettier -c resources/styles -c src/**/*.scss",
"lint:scss:fix": "yarn run prettier -c resources/styles -c src/**/*.scss -w", "lint:scss:fix": "yarn run prettier -c resources/styles -c src/**/*.scss -w",
"lint:clj": "clj-kondo --parallel --lint src/", "test": "yarn run test:compile && yarn run test:run",
"test:compile": "clojure -M:dev:shadow-cljs compile test --config-merge '{:autorun false}'", "test:compile": "clojure -M:dev:shadow-cljs compile test --config-merge '{:autorun false}'",
"test:run": "node target/tests.cjs", "test:run": "node target/tests.cjs",
"test:watch": "clojure -M:dev:shadow-cljs watch test", "test:watch": "clojure -M:dev:shadow-cljs watch test",
"test": "yarn run test:compile && yarn run test:run",
"translations": "node ./scripts/translations.js", "translations": "node ./scripts/translations.js",
"translations:find-unused": "node ./scripts/find-unused-translations.js", "watch": "yarn run watch:app:assets",
"compile": "node ./scripts/compile.js", "watch:app:assets": "node ./scripts/watch.js",
"compile:cljs": "clojure -M:dev:shadow-cljs compile main", "watch:storybook": "concurrently \"clojure -M:dev:shadow-cljs watch storybook\" \"storybook dev -p 6006 --no-open\" \"yarn run watch:storybook:assets\"",
"watch": "node ./scripts/watch.js", "watch:storybook:assets": "node ./scripts/watch-storybook.js"
"e2e:server": "node ./scripts/e2e-server.js",
"e2e:test": "playwright test --project default",
"storybook:compile": "yarn run compile && clojure -M:dev:shadow-cljs compile storybook",
"storybook:server": "yarn run storybook dev -p 6006 --no-open",
"storybook:watch": "concurrently \"clojure -M:dev:shadow-cljs watch storybook\" \"yarn run storybook:server\" \"yarn run watch\"",
"storybook:build": "yarn run storybook:compile && storybook build"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "1.44.1", "@playwright/test": "1.44.1",

View file

@ -1,4 +1,4 @@
<link href="/css/main.css" rel="stylesheet" type="text/css" /> <link href="/css/ds.css?ts={{& ts}}" rel="stylesheet" type="text/css" />
<style> <style>
body { body {
overflow-y: scroll; overflow-y: scroll;
@ -7,4 +7,4 @@
#storybook-root { #storybook-root {
height: 100%; height: 100%;
} }
</style> </style>

View file

@ -82,6 +82,31 @@ export async function compileSassDebug(worker) {
return `${result.css}\n`; return `${result.css}\n`;
} }
export async function compileSassStorybook(worker) {
const limitFn = pLimit(4);
const sourceDir = ph.join("src", "app", "main", "ui", "ds");
const dsFiles = (await fs.readdir(sourceDir, { recursive: true }))
.filter(isSassFile)
.map((filename) => ph.join(sourceDir, filename));
const procs = [compileSass(worker, "resources/styles/main-default.scss", {})];
for (let path of dsFiles) {
const proc = limitFn(() => compileSass(worker, path, { modules: true }));
procs.push(proc);
}
const result = await Promise.all(procs);
return result.reduce(
(acc, item) => {
acc.index[item.outputPath] = item.css;
acc.items.push(item.outputPath);
return acc;
},
{ index: {}, items: [] },
);
}
export async function compileSassAll(worker) { export async function compileSassAll(worker) {
const limitFn = pLimit(4); const limitFn = pLimit(4);
const sourceDir = "src"; const sourceDir = "src";
@ -379,6 +404,15 @@ async function generateTemplates() {
); );
await fs.writeFile("./.storybook/preview-body.html", content); await fs.writeFile("./.storybook/preview-body.html", content);
content = await renderTemplate(
"resources/templates/preview-head.mustache",
{
manifest: manifest,
},
partials,
);
await fs.writeFile("./.storybook/preview-head.html", content);
content = await renderTemplate("resources/templates/render.mustache", { content = await renderTemplate("resources/templates/render.mustache", {
manifest: manifest, manifest: manifest,
translations: JSON.stringify(translations), translations: JSON.stringify(translations),
@ -394,6 +428,22 @@ async function generateTemplates() {
await fs.writeFile("./resources/public/rasterizer.html", content); await fs.writeFile("./resources/public/rasterizer.html", content);
} }
export async function compileStorybookStyles() {
const worker = startWorker();
const start = process.hrtime();
log.info("init: compile storybook styles");
let result = await compileSassStorybook(worker);
result = concatSass(result);
await fs.mkdir("./resources/public/css", { recursive: true });
await fs.writeFile("./resources/public/css/ds.css", result);
const end = process.hrtime(start);
log.info("done: compile storybook styles", `(${ppt(end)})`);
worker.terminate();
}
export async function compileStyles() { export async function compileStyles() {
const worker = startWorker(); const worker = startWorker();
const start = process.hrtime(); const start = process.hrtime();

View file

@ -4,6 +4,8 @@
set -ex set -ex
export INCLUDE_STORYBOOK=${BUILD_STORYBOOK:-no};
export CURRENT_VERSION=$1; export CURRENT_VERSION=$1;
export BUILD_DATE=$(date -R); export BUILD_DATE=$(date -R);
export CURRENT_HASH=${CURRENT_HASH:-$(git rev-parse --short HEAD)}; export CURRENT_HASH=${CURRENT_HASH:-$(git rev-parse --short HEAD)};
@ -20,9 +22,16 @@ rm -rf target/dist;
clojure -M:dev:shadow-cljs release main --config-merge "{:release-version \"${CURRENT_HASH}-${TS}\"}" $EXTRA_PARAMS || exit 1 clojure -M:dev:shadow-cljs release main --config-merge "{:release-version \"${CURRENT_HASH}-${TS}\"}" $EXTRA_PARAMS || exit 1
yarn run compile || exit 1; yarn run build:app:assets || exit 1;
mkdir -p target/dist; mkdir -p target/dist;
rsync -avr resources/public/ target/dist/ rsync -avr resources/public/ target/dist/
sed -i -re "s/\%version\%/$CURRENT_VERSION/g" ./target/dist/index.html; sed -i -re "s/\%version\%/$CURRENT_VERSION/g" ./target/dist/index.html;
sed -i -re "s/\%buildDate\%/$BUILD_DATE/g" ./target/dist/index.html; sed -i -re "s/\%buildDate\%/$BUILD_DATE/g" ./target/dist/index.html;
if [ "$INCLUDE_STORYBOOK" = "yes"]; then
# build storybook
yarn run build:storybook || exit 1;
rsync -avr storybook-static/ target/dist/storybook-static;
fi

View file

@ -0,0 +1,7 @@
import * as h from "./_helpers.js";
await h.compileStorybookStyles();
await h.copyAssets();
await h.compileSvgSprites();
await h.compileTemplates();
await h.compilePolyfills();

View file

@ -0,0 +1,86 @@
import fs from "node:fs/promises";
import ph from "node:path";
import log from "fancy-log";
import * as h from "./_helpers.js";
import ppt from "pretty-time";
const worker = h.startWorker();
let sass = null;
async function compileSassAll() {
const start = process.hrtime();
log.info("init: compile storybook styles");
sass = await h.compileSassStorybook(worker);
let output = await h.concatSass(sass);
await fs.writeFile("./resources/public/css/ds.css", output);
const end = process.hrtime(start);
log.info("done: compile storybook styles", `(${ppt(end)})`);
}
async function compileSass(path) {
const start = process.hrtime();
log.info("changed:", path);
const result = await h.compileSass(worker, path, { modules: true });
sass.index[result.outputPath] = result.css;
const output = h.concatSass(sass);
await fs.writeFile("./resources/public/css/ds.css", output);
const end = process.hrtime(start);
log.info("done:", `(${ppt(end)})`);
}
await fs.mkdir("./resources/public/css/", { recursive: true });
await compileSassAll();
await h.copyAssets();
await h.compileSvgSprites();
await h.compileTemplates();
await h.compilePolyfills();
log.info("watch: scss src (~)");
h.watch("src", h.isSassFile, async function (path) {
const isPartial = ph.basename(path).startsWith("_");
const isCommon = isPartial || ph.dirname(path).endsWith("/ds");
if (isCommon) {
await compileSassAll(path);
} else {
await compileSass(path);
}
});
log.info("watch: scss: resources (~)");
h.watch("resources/styles", h.isSassFile, async function (path) {
log.info("changed:", path);
await compileSassAll();
});
log.info("watch: templates (~)");
h.watch("resources/templates", null, async function (path) {
log.info("changed:", path);
await h.compileTemplates();
});
log.info("watch: translations (~)");
h.watch("translations", null, async function (path) {
log.info("changed:", path);
await h.compileTemplates();
});
log.info("watch: assets (~)");
h.watch(
["resources/images", "resources/fonts", "resources/plugins-runtime"],
null,
async function (path) {
log.info("changed:", path);
await h.compileSvgSprites();
await h.copyAssets();
await h.compileTemplates();
},
);
worker.terminate();

View file

@ -93,7 +93,7 @@
{:entries []} {:entries []}
:components :components
{:exports {:default app.main.ui.ds/default} {:exports {default app.main.ui.ds/default}
:depends-on #{:base}}} :depends-on #{:base}}}
:compiler-options :compiler-options

View file

@ -1,15 +1,14 @@
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import { configDefaults } from 'vitest/config' import { configDefaults } from "vitest/config";
import { resolve } from "path"; import { resolve } from "path";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
test: { test: {
exclude: [...configDefaults.exclude, 'target/**', 'resources/**'], exclude: [...configDefaults.exclude, "target/**", "resources/**"],
environment: 'jsdom' environment: "jsdom",
}, },
resolve: { resolve: {
alias: { alias: {
"@target": resolve(__dirname, "./target/storybook"), "@target": resolve(__dirname, "./target/storybook"),