Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor all of our various cra build steps #9907

Merged
merged 5 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 84 additions & 90 deletions cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import * as pyconv from './pyconv';
import * as gitfs from './gitfs';
import * as crowdin from './crowdin';
import * as youtube from './youtube';
import { SUB_WEBAPPS } from './subwebapp';

const rimraf: (f: string, opts: any, cb: (err: Error, res: any) => void) => void = require('rimraf');

Expand All @@ -40,6 +41,7 @@ let forceBuild = false; // don't use cache

Error.stackTraceLimit = 100;


function parseHwVariant(parsed: commandParser.ParsedCommand) {
let hwvariant = parsed && parsed.flags["hwvariant"] as string;
if (hwvariant) {
Expand Down Expand Up @@ -354,23 +356,16 @@ function onlyExts(files: string[], exts: string[]) {
}

function pxtFileList(pref: string) {
return nodeutil.allFiles(pref + "webapp/public")
let allFiles = nodeutil.allFiles(pref + "webapp/public")
.concat(onlyExts(nodeutil.allFiles(pref + "built/web", { maxDepth: 1 }), [".js", ".css"]))
.concat(nodeutil.allFiles(pref + "built/web/fonts", { maxDepth: 1 }))
.concat(nodeutil.allFiles(pref + "built/web/vs", { maxDepth: 4 }))
.concat(nodeutil.allFiles(pref + "built/web/skillmap", { maxDepth: 4 }))
.concat(nodeutil.allFiles(pref + "built/web/authcode", { maxDepth: 4 }))
.concat(nodeutil.allFiles(pref + "built/web/multiplayer", { maxDepth: 4 }))
.concat(nodeutil.allFiles(pref + "built/web/kiosk", { maxDepth: 4 }))
.concat(nodeutil.allFiles(pref + "built/web/teachertool", { maxDepth: 4 }))
}
.concat(nodeutil.allFiles(pref + "built/web/vs", { maxDepth: 4 }));

function semverCmp(a: string, b: string) {
let parse = (s: string) => {
let v = s.split(/\./).map(parseInt)
return v[0] * 100000000 + v[1] * 10000 + v[2]
for (const subapp of SUB_WEBAPPS) {
allFiles = allFiles.concat(nodeutil.allFiles(pref + `built/web/${subapp.name}`, { maxDepth: 4 }))
}
return parse(a) - parse(b)

return allFiles;
}

function checkIfTaggedCommitAsync() {
Expand All @@ -394,7 +389,7 @@ function checkIfTaggedCommitAsync() {

let readJson = nodeutil.readJson;

function ciAsync() {
async function ciAsync() {
forceCloudBuild = true;
const buildInfo = ciBuildInfo();
pxt.log(`ci build using ${buildInfo.ci}`);
Expand Down Expand Up @@ -447,54 +442,54 @@ function ciAsync() {
let pkg = readJson("package.json")
if (pkg["name"] == "pxt-core") {
pxt.log("pxt-core build");
return checkIfTaggedCommitAsync()
.then(isTaggedCommit => {
pxt.log(`is tagged commit: ${isTaggedCommit}`);
let p = npmPublishAsync();
if (branch === "master" && isTaggedCommit) {
if (uploadDocs)
p = p
.then(() => buildWebStringsAsync())
.then(() => crowdin.execCrowdinAsync("upload", "built/webstrings.json"))
.then(() => crowdin.execCrowdinAsync("upload", "built/skillmap-strings.json"))
.then(() => crowdin.execCrowdinAsync("upload", "built/authcode-strings.json"))
.then(() => crowdin.execCrowdinAsync("upload", "built/multiplayer-strings.json"))
.then(() => crowdin.execCrowdinAsync("upload", "built/kiosk-strings.json"))
.then(() => crowdin.execCrowdinAsync("upload", "built/teachertool-strings.json"));
if (uploadApiStrings)
p = p.then(() => crowdin.execCrowdinAsync("upload", "built/strings.json"))
if (uploadDocs || uploadApiStrings)
p = p.then(() => crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs));

const isTaggedCommit = await checkIfTaggedCommitAsync();
pxt.log(`is tagged commit: ${isTaggedCommit}`);
await npmPublishAsync();
if (branch === "master" && isTaggedCommit) {
if (uploadDocs) {
await buildWebStringsAsync();
await crowdin.execCrowdinAsync("upload", "built/webstrings.json");

for (const subapp of SUB_WEBAPPS) {
await crowdin.execCrowdinAsync("upload", `built/${subapp.name}-strings.json`);
}
return p;
});
}
if (uploadApiStrings) {
await crowdin.execCrowdinAsync("upload", "built/strings.json");
}
if (uploadDocs || uploadApiStrings) {
await crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs);
pxt.log("translations uploaded");
}
else {
pxt.log("skipping translations upload");
}
}
} else {
pxt.log("target build");
return internalBuildTargetAsync()
.then(() => internalCheckDocsAsync(true))
.then(() => blockTestsAsync())
.then(() => npmPublishAsync())
.then(() => {
if (!process.env["PXT_ACCESS_TOKEN"]) {
// pull request, don't try to upload target
pxt.log('no token, skipping upload')
return Promise.resolve();
}
const trg = readLocalPxTarget();
const label = `${trg.id}/${tag || latest}`;
pxt.log(`uploading target with label ${label}...`);
return uploadTargetAsync(label);
})
.then(() => {
pxt.log("target uploaded");
if (uploadDocs || uploadApiStrings) {
return crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs)
.then(() => pxt.log("translations uploaded"));
} else {
pxt.log("skipping translations upload");
return Promise.resolve();
}
});
await internalBuildTargetAsync();
await internalCheckDocsAsync(true);
await blockTestsAsync();
await npmPublishAsync();

if (!process.env["PXT_ACCESS_TOKEN"]) {
// pull request, don't try to upload target
pxt.log('no token, skipping upload')
return;
}
const trg = readLocalPxTarget();
const label = `${trg.id}/${tag || latest}`;
pxt.log(`uploading target with label ${label}...`);
await uploadTargetAsync(label);

pxt.log("target uploaded");
if (uploadDocs || uploadApiStrings) {
await crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs);
pxt.log("translations uploaded");
} else {
pxt.log("skipping translations upload");
}
}
}

Expand Down Expand Up @@ -1021,7 +1016,7 @@ function uploadCoreAsync(opts: UploadOptions) {
}

if (opts.localDir) {
let cfg: pxt.WebConfig = {
let cfg: Partial<pxt.WebConfig> = {
"relprefix": opts.localDir,
"verprefix": "",
"workerjs": opts.localDir + "worker.js",
Expand All @@ -1047,13 +1042,13 @@ function uploadCoreAsync(opts: UploadOptions) {
"docsUrl": opts.localDir + "docs.html",
"multiUrl": opts.localDir + "multi.html",
"asseteditorUrl": opts.localDir + "asseteditor.html",
"skillmapUrl": opts.localDir + "skillmap.html",
"authcodeUrl": opts.localDir + "authcode.html",
"multiplayerUrl": opts.localDir + "multiplayer.html",
"kioskUrl": opts.localDir + "kiosk.html",
"teachertoolUrl": opts.localDir + "teachertool.html",
"isStatic": true,
}

for (const subapp of SUB_WEBAPPS) {
(cfg as any)[subapp.name + "Url"] = opts.localDir + subapp.name + ".html";
}

const targetImageLocalPaths = targetImagePaths.map(k =>
`${opts.localDir}${path.join('./docs', k)}`);

Expand Down Expand Up @@ -1100,25 +1095,20 @@ function uploadCoreAsync(opts: UploadOptions) {
"sim.webmanifest",
"workerConfig.js",
"multi.html",
"asseteditor.html",
"skillmap.html",
"authcode.html",
"multiplayer.html",
"kiosk.html",
"teachertool.html",
"asseteditor.html"
]

// expandHtml is manually called on these files before upload
// runs <!-- @include --> substitutions, fills in locale, etc
const expandFiles = [
"index.html",
"skillmap.html",
"authcode.html",
"multiplayer.html",
"kiosk.html",
"teachertool.html",
"index.html"
]

for (const subapp of SUB_WEBAPPS) {
replFiles.push(`${subapp.name}.html`);
expandFiles.push(`${subapp.name}.html`);
}

nodeutil.mkdirP("built/uploadrepl")

function encodeURLs(urls: string[]) {
Expand Down Expand Up @@ -2043,11 +2033,10 @@ async function buildSemanticUIAsync(parsed?: commandParser.ParsedCommand) {
}

// Generate react-common css for skillmap, authcode, and multiplayer (but not kiosk yet)
await Promise.all([
generateReactCommonCss("skillmap"),
generateReactCommonCss("authcode"),
generateReactCommonCss("multiplayer"),
]);

await Promise.all(
SUB_WEBAPPS.filter(app => app.buildCss).map(app => generateReactCommonCss(app.name))
);

// Run postcss with autoprefixer and rtlcss
pxt.debug("running postcss");
Expand All @@ -2072,12 +2061,15 @@ async function buildSemanticUIAsync(parsed?: commandParser.ParsedCommand) {
const rtlcss = require("rtlcss");
const files = [
"semantic.css",
"blockly.css",
"react-common-skillmap.css",
"react-common-authcode.css",
"react-common-multiplayer.css"
"blockly.css"
];

for (const subapp of SUB_WEBAPPS) {
if (subapp.buildCss) {
files.push(`react-common-${subapp.name}.css`);
}
}

for (const cssFile of files) {
const css = await readFileAsync(`built/web/${cssFile}`, "utf8");
const processed = await postcss([cssnano])
Expand All @@ -2093,10 +2085,12 @@ async function buildSemanticUIAsync(parsed?: commandParser.ParsedCommand) {

if (!isPxtCore) {
// This is just to support the local skillmap/cra-app serve for development
nodeutil.cp("built/web/react-common-skillmap.css", "node_modules/pxt-core/skillmap/public/blb");
nodeutil.cp("built/web/react-common-authcode.css", "node_modules/pxt-core/authcode/public/blb");
nodeutil.cp("built/web/semantic.css", "node_modules/pxt-core/skillmap/public/blb");
nodeutil.cp("built/web/semantic.css", "node_modules/pxt-core/authcode/public/blb");
for (const subapp of SUB_WEBAPPS) {
if (subapp.buildCss) {
nodeutil.cp(`built/web/react-common-${subapp.name}.css`, `node_modules/pxt-core/${subapp.name}/public/blb`);
nodeutil.cp(`built/web/semantic.css`, `node_modules/pxt-core/${subapp.name}/public/blb`);
}
}
}
}

Expand Down
20 changes: 6 additions & 14 deletions cli/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import * as querystring from 'querystring';
import * as nodeutil from './nodeutil';
import * as hid from './hid';
import * as net from 'net';
import * as crowdin from './crowdin';
import * as storage from './storage';
import { SUB_WEBAPPS } from './subwebapp';

import { promisify } from "util";

Expand Down Expand Up @@ -1184,19 +1184,11 @@ export function serveAsync(options: ServeOptions) {
return
}

if (pathname == "/--skillmap") {
sendFile(path.join(publicDir, 'skillmap.html'));
return
}

if (pathname == "/--authcode") {
sendFile(path.join(publicDir, 'authcode.html'));
return
}

if (pathname == "/--multiplayer") {
sendFile(path.join(publicDir, 'multiplayer.html'));
return
for (const subapp of SUB_WEBAPPS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub won't let me make comments higher up in the file, but up at line 28, there's a webappNames array we'll need to update for apps that have localServe set to false. Slight quirk in that teachertool's is not actually teachertool, it's "eval". May need add an extra field for publicName or endpointName or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, good catch. lemme see what i can do here...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!

if (subapp.localServe && pathname === `/--${subapp.name}`) {
sendFile(path.join(publicDir, `${subapp.name}.html`));
return
}
}

if (/\/-[-]*docs.*$/.test(pathname)) {
Expand Down
28 changes: 28 additions & 0 deletions cli/subwebapp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// All of our various create react apps
export const SUB_WEBAPPS = [
{
name: "kiosk",
buildCss: false,
localServe: false
},
{
name: "teachertool",
buildCss: false,
localServe: false
},
{
name: "skillmap",
buildCss: true,
localServe: true
},
{
name: "multiplayer",
buildCss: true,
localServe: true
},
{
name: "authcode",
buildCss: true,
localServe: true
},
];
Loading