Skip to content

Commit

Permalink
Github Actions
Browse files Browse the repository at this point in the history
Travis went paid, Actions is free
  • Loading branch information
Fevix committed Nov 3, 2024
1 parent c6979e0 commit 5f0e743
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 12 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: JSON linter + luacheck
on: [push, pull_request, workflow_dispatch]
jobs:
# Check JSON assets for syntax errors.
json-linter:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: ( cd tests/ci && npm install )
- name: RUN -- npm test
run: ( cd tests/ci && npm test )
# Check Lua files with "luacheck" tool (Lua static analyzer).
luacheck:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: sudo apt-get install -y luarocks && sudo luarocks install luacheck
# Don't fail if the exit code is 1 (which means "there were warnings, but no errors"),
# only on exit code 2 ("there were errors").
- name: RUN -- luacheck .
run: luacheck --no-color . || [[ $? -le 1 ]]
33 changes: 33 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
std = "lua53c"
max_line_length = 200
ignore = {
-- due to how Starbound isolates Lua files, not using "local" for these variables is not a problem.
"111", -- "setting non-standard global variable [...]"
"112", -- "mutating non-standard global variable [...]"
"113" -- "accessing undefined variable [...]"
}
-- These global variables are allowed.
globals = {
"item",
"self",
"storage"
}
-- These global variables are allowed, but can't be modified.
-- These are mainly things from https://starbounder.org/Modding:Lua
read_globals = {
"config",
"entity",
"monster",
"npc",
"object",
"player",
"root",
"world"
}
codes = true -- Show luacheck's error/warning codes. Useful for adding exceptions.
-- Ignore "unused argument self" (W212) in object-oriented methods like widgetBase:hasMouse()
self = false
exclude_files = {
"**/*unused*",
"**/*UNUSED*"
}
12 changes: 0 additions & 12 deletions .travis.yml

This file was deleted.

99 changes: 99 additions & 0 deletions tests/ci/check_json_assets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
* Find all JSON files and check them for correctness.
*/
'use strict';
const fs = require( 'fs' ),
process = require( 'process' ),
glob = require( 'fast-glob' ),
stripJsonComments = require( 'strip-json-comments' );
/**
* Turn non-strict JSON (with comments, newlines, etc.) into a string suitable for JSON.parse().
* From https://github.com/edwardspec/fudocgenerator/
* @param {string} relaxedJson
* @return {string}
*/
function sanitizeRelaxedJson( relaxedJson ) {
// Some input files have "new line" character within the JSON strings (between " and ").
// This is invalid JSON (would cause syntax error), but we must be tolerant to such input.
// This is especially important for weapons/tools, as most of them have multiline descriptions.
var sanitizedJson = '',
isInsideQuotes = false,
prevChar = '';
// Remove comments (JSON standard doesn't allow them).
relaxedJson = stripJsonComments( relaxedJson );
// Remove both \r and BOM (byte order mark) symbols, because they confuse JSON.parse().
relaxedJson = relaxedJson.replace( /(\uFEFF|\r)/g, '' );
// Iterate over each character, and if we find "new line" or "tab" characters inside the quotes,
// replace them with "\n" and "\t" respectively, making this a valid JSON.
[...relaxedJson].forEach( char => {
// Non-escaped " means that this is start/end of a string.
if ( char == '"' && prevChar != '\\' ) {
isInsideQuotes = !isInsideQuotes;
} else if ( isInsideQuotes ) {
switch ( char ) {
case '\n':
char = '\\n';
break;
case '\t':
char = '\\t';
}
}
sanitizedJson += char;
prevChar = char;
} );
return sanitizedJson;
}
/**
* Make error from JSON.parse() more readable by adding "text before/after the position of error".
* Normal error like "Unexpected token { in JSON at position 1005" is inconvenient to troubleshoot.
* @param {Error} exception Exception thrown by JSON.parse().
* @param {string} sourceCode String that was passed to JSON.parse() as parameter.
* @return {string} Improved error message.
* Example of improved message:
* ... "path": "/a", "value": 123 } <<<SYNTAX ERROR HERE>>>{ "op": "add", "path": "/b" ...
*/
function addContextToJsonError( exception, sourceCode ) {
var errorMessage = exception.message;
var match = errorMessage.match( 'at position ([0-9]+)' );
if ( match ) {
// We are quoting symbolsToQuote before AND symbolsToQuote after the error position.
// As such, up to 2*symbolsToQuote symbols can be quoted.
var symbolsToQuote = 100,
position = parseInt( match[1] ),
quoteBefore = sourceCode.substring( 0, position ).replace( /\s+/g, ' ' ),
quoteAfter = sourceCode.substring( position ).replace( /\s+/g, ' ' );
quoteBefore = quoteBefore.substring( quoteBefore.length - symbolsToQuote );
quoteAfter = quoteAfter.substring( 0, symbolsToQuote );
errorMessage += '\n\t... ' + quoteBefore + '<<<SYNTAX ERROR HERE>>>' + quoteAfter + ' ...';
}
return errorMessage;
}
// This script is under tests/travis/
var directory = __dirname + '/../..';
var globOptions = {
cwd: directory,
ignore: [
// Exclude everything that is not a JSON asset: images, documentation, examples, etc.
'tests',
'_previewimage',
'**/*.{lua,png,xcf,wav,ogg,txt,md,ase,aseprite,tsx,aup,ico,tmx,pdn,zip,au,old,unused}'
],
caseSensitiveMatch: false
};
var totalCount = 0,
failedCount = 0;
var filenames = glob.sync( '**', globOptions ).concat( [ '_metadata' ] );
filenames.forEach( ( filename ) => {
var jsonString = sanitizeRelaxedJson( fs.readFileSync( directory + '/' + filename ).toString() );
try {
JSON.parse( jsonString );
} catch ( error ) {
console.log( '\n', filename, addContextToJsonError( error, jsonString ) );
failedCount ++;
}
if ( ++ totalCount % 2500 == 0 ) {
process.stdout.write( totalCount + ' ' );
}
} );
process.stdout.write( '\nChecked ' + totalCount + ' JSON files. Errors: ' + failedCount + '.\n' );
process.exit( failedCount > 0 ? 1 : 0 );
14 changes: 14 additions & 0 deletions tests/ci/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"private": true,
"dependencies": {
"fast-glob": "^3.2.4",
"fs": "^0.0.2",
"strip-json-comments": "^3.1.1"
},
"devDependencies": {
"eslint": "^7.6.0"
},
"scripts": {
"test": "node check_json_assets.js"
}
}

0 comments on commit 5f0e743

Please sign in to comment.