summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Müllner <fmuellner@gnome.org>2022-02-17 22:54:22 +0100
committerMarge Bot <marge-bot@gnome.org>2023-04-21 18:28:32 +0000
commit0a420404c6035b66706c5b5747e9f04d64a75e6f (patch)
tree682300e3f2784cc7f94664d908614696b3169c1c
parentddae41456dff308d6ba2bd7fd47033b5eb6d5e4b (diff)
downloadgnome-shell-0a420404c6035b66706c5b5747e9f04d64a75e6f.tar.gz
ci: Update JS tooling
Provided we use the correct version of the SpiderMonkey shell, we can perform checks using the same engine that is used by gjs. However some engine features are opt-in, so the set of features enabled by gjs and js102 may differ. The obvious option for avoiding this is replacing js102 with gjs for tests. For that reason the check-potfiles.js script has been ported to gjs and a second (simpler) script to replace `js102 --compileonly` was added. This work happened in a separate repository to make sharing between different JS-based projects easier. Update the CI image to pull in those scripts and include gjs. This will also address the issue that `js102 --compileonly` does not handle modules. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2193>
-rw-r--r--.gitlab-ci.yml24
-rw-r--r--.gitlab-ci/check-potfiles.js207
2 files changed, 14 insertions, 217 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0fba285bc..db4a4a8b2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -28,7 +28,6 @@ default:
variables:
FDO_UPSTREAM_REPO: GNOME/gnome-shell
BUNDLE: "extensions-git.flatpak"
- JS_LOG: "js-report.txt"
LINT_LOG: "eslint-report.xml"
LINT_MR_LOG: "eslint-mr-report.xml"
@@ -49,13 +48,13 @@ workflow:
.gnome-shell.fedora:
variables:
FDO_DISTRIBUTION_VERSION: 38
- FDO_DISTRIBUTION_TAG: '2023-04-20.0'
+ FDO_DISTRIBUTION_TAG: '2023-04-21.1'
FDO_DISTRIBUTION_PACKAGES:
- findutils
- mozjs102-devel
+ gjs
nodejs
npm
meson
+ pkgconfig(gobject-introspection-1.0)
pkgconfig(gio-2.0)
pkgconfig(gio-unix-2.0)
pkgconfig(gnome-autoar-0)
@@ -68,6 +67,10 @@ workflow:
'C Development Tools and Libraries' &&
./.gitlab-ci/install-meson-project.sh \
+ https://gitlab.gnome.org/fmuellner/gjs-ci-tools.git \
+ main &&
+
+ ./.gitlab-ci/install-meson-project.sh \
--subdir subprojects/extensions-tool/ \
--prepare ./generate-translations.sh \
-Dman=false \
@@ -126,12 +129,10 @@ js_check:
- .gnome-shell.fedora
stage: review
script:
- - find js -name '*.js' $(printf "! -wholename %s " $(cat .jscheckignore)) -exec js102 -c '{}' ';' 2>&1 | tee $JS_LOG
- - (! grep -q . $JS_LOG)
+ - gjs-check-syntax
artifacts:
- paths:
- - ${JS_LOG}
- when: on_failure
+ reports:
+ junit: gjs-check-syntax.junit.xml
eslint:
extends:
@@ -177,7 +178,10 @@ potfile_js_check:
- .gnome-shell.fedora
stage: review
script:
- - js102 -m .gitlab-ci/check-potfiles.js
+ - gjs-check-potfiles
+ artifacts:
+ reports:
+ junit: gjs-check-potfiles.junit.xml
build:
stage: build
diff --git a/.gitlab-ci/check-potfiles.js b/.gitlab-ci/check-potfiles.js
deleted file mode 100644
index 0c8885e25..000000000
--- a/.gitlab-ci/check-potfiles.js
+++ /dev/null
@@ -1,207 +0,0 @@
-const gettextFuncs = new Set([
- '_',
- 'N_',
- 'C_',
- 'NC_',
- 'dcgettext',
- 'dgettext',
- 'dngettext',
- 'dpgettext',
- 'gettext',
- 'ngettext',
- 'pgettext',
-]);
-
-function dirname(file) {
- const split = file.split('/');
- split.pop();
- return split.join('/');
-}
-
-const scriptDir = dirname(import.meta.url);
-const root = dirname(scriptDir);
-
-const excludedFiles = new Set();
-const foundFiles = new Set()
-
-function addExcludes(filename) {
- const contents = os.file.readFile(filename);
- const lines = contents.split('\n')
- .filter(l => l && !l.startsWith('#'));
- lines.forEach(line => excludedFiles.add(line));
-}
-
-addExcludes(`${root}/po/POTFILES.in`);
-addExcludes(`${root}/po/POTFILES.skip`);
-
-function walkAst(node, func) {
- func(node);
- nodesToWalk(node).forEach(n => walkAst(n, func));
-}
-
-function findGettextCalls(node) {
- switch(node.type) {
- case 'CallExpression':
- if (node.callee.type === 'Identifier' &&
- gettextFuncs.has(node.callee.name))
- throw new Error();
- if (node.callee.type === 'MemberExpression' &&
- node.callee.object.type === 'Identifier' &&
- node.callee.object.name === 'Gettext' &&
- node.callee.property.type === 'Identifier' &&
- gettextFuncs.has(node.callee.property.name))
- throw new Error();
- break;
- }
- return true;
-}
-
-function nodesToWalk(node) {
- switch(node.type) {
- case 'ArrayPattern':
- case 'BreakStatement':
- case 'CallSiteObject': // i.e. strings passed to template
- case 'ContinueStatement':
- case 'DebuggerStatement':
- case 'EmptyStatement':
- case 'Identifier':
- case 'Literal':
- case 'MetaProperty': // i.e. new.target
- case 'Super':
- case 'ThisExpression':
- return [];
- case 'ArrowFunctionExpression':
- case 'FunctionDeclaration':
- case 'FunctionExpression':
- return [...node.defaults, node.body].filter(n => !!n);
- case 'AssignmentExpression':
- case 'BinaryExpression':
- case 'ComprehensionBlock':
- case 'LogicalExpression':
- return [node.left, node.right];
- case 'ArrayExpression':
- case 'TemplateLiteral':
- return node.elements.filter(n => !!n);
- case 'BlockStatement':
- case 'Program':
- return node.body;
- case 'StaticClassBlock':
- return [node.body];
- case 'ClassField':
- return [node.name, node.init];
- case 'CallExpression':
- case 'NewExpression':
- case 'OptionalCallExpression':
- case 'TaggedTemplate':
- return [node.callee, ...node.arguments];
- case 'CatchClause':
- return [node.body, node.guard].filter(n => !!n);
- case 'ClassExpression':
- case 'ClassStatement':
- return [...node.body, node.superClass].filter(n => !!n);
- case 'ClassMethod':
- return [node.name, node.body];
- case 'ComprehensionExpression':
- case 'GeneratorExpression':
- return [node.body, ...node.blocks, node.filter].filter(n => !!n);
- case 'ComprehensionIf':
- return [node.test];
- case 'ComputedName':
- return [node.name];
- case 'ConditionalExpression':
- case 'IfStatement':
- return [node.test, node.consequent, node.alternate].filter(n => !!n);
- case 'DoWhileStatement':
- case 'WhileStatement':
- return [node.body, node.test];
- case 'ExportDeclaration':
- return [node.declaration, node.source].filter(n => !!n);
- case 'ImportDeclaration':
- return [...node.specifiers, node.source];
- case 'LetStatement':
- return [...node.head, node.body];
- case 'ExpressionStatement':
- return [node.expression];
- case 'ForInStatement':
- case 'ForOfStatement':
- return [node.body, node.left, node.right];
- case 'ForStatement':
- return [node.init, node.test, node.update, node.body].filter(n => !!n);
- case 'LabeledStatement':
- return [node.body];
- case 'MemberExpression':
- return [node.object, node.property];
- case 'ObjectExpression':
- case 'ObjectPattern':
- return node.properties;
- case 'OptionalExpression':
- return [node.expression];
- case 'OptionalMemberExpression':
- return [node.object, node.property];
- case 'Property':
- case 'PrototypeMutation':
- return [node.value];
- case 'ReturnStatement':
- case 'ThrowStatement':
- case 'UnaryExpression':
- case 'UpdateExpression':
- case 'YieldExpression':
- return node.argument ? [node.argument] : [];
- case 'SequenceExpression':
- return node.expressions;
- case 'SpreadExpression':
- return [node.expression];
- case 'SwitchCase':
- return [node.test, ...node.consequent].filter(n => !!n);
- case 'SwitchStatement':
- return [node.discriminant, ...node.cases];
- case 'TryStatement':
- return [node.block, node.handler, node.finalizer].filter(n => !!n);
- case 'VariableDeclaration':
- return node.declarations;
- case 'VariableDeclarator':
- return node.init ? [node.init] : [];
- case 'WithStatement':
- return [node.object, node.body];
- default:
- print(`Ignoring ${node.type}, you should probably fix this in the script`);
- }
-}
-
-function walkDir(dir) {
- os.file.listDir(dir).forEach(child => {
- if (child.startsWith('.'))
- return;
-
- const path = os.path.join(dir, child);
- const relativePath = path.replace(`${root}/`, '');
- if (excludedFiles.has(relativePath))
- return;
-
- if (!child.endsWith('.js')) {
- try {
- walkDir(path);
- } catch (e) {
- // not a directory
- }
- return;
- }
-
- try {
- const script = os.file.readFile(path);
- const ast = Reflect.parse(script);
- walkAst(ast, findGettextCalls);
- } catch (e) {
- foundFiles.add(path);
- }
- });
-}
-
-walkDir(root);
-
-if (foundFiles.size === 0)
- quit(0);
-
-print('The following files are missing from po/POTFILES.in:')
-foundFiles.forEach(f => print(` ${f}`));
-quit(1);