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) @@ -67,6 +66,10 @@ workflow: dnf group install -y 'Development Tools' \ '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 \ @@ -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);