commit fd580bda03ed76d82f0f16a2f48fd50ebaa9bf7f Author: olemorud Date: Tue Mar 14 12:58:38 2023 +0100 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..f02be5b --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# GCC problem matcher + +Creates annotations for warnings and errors in gcc builds. + + +## Usage + +Just add a single line before running the build step. + +```yaml + - uses: olemorud/gcc-problem-matcher@master +``` diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..86bcd6d --- /dev/null +++ b/action.yml @@ -0,0 +1,19 @@ +name: GCC Problem Matcher + +description: Get annotations for warnings and errors on builds using gcc + +author: Ole Morud + +branding: + icon: search + color: yellow + +inputs: + root: + description: 'base directory for build, e.g. /workdir/build' + required: false + default: '' + +runs: + using: 'node16' + main: 'src/index.js' \ No newline at end of file diff --git a/src/gcc_matcher.jsontemplate b/src/gcc_matcher.jsontemplate new file mode 100644 index 0000000..0c338d9 --- /dev/null +++ b/src/gcc_matcher.jsontemplate @@ -0,0 +1,17 @@ +{ + "problemMatcher": [ + { + "owner": "gcc-problem-matcher", + "pattern": [ + { + "regexp": "^${{ BASE }}\/?(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + ] + } + ] +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..6045738 --- /dev/null +++ b/src/index.js @@ -0,0 +1,33 @@ +const path = require('path'); +const fs = require('node:fs'); +//const core = require('@actions/core'); + +// C:\Users\ => C\:\\Users\\ +const escapeRegExp = (s) => + s.replace(/[:.*+?^${}()|\/[\]\\]/g, "\\$&"); + + +// ${{ key }}, ${{var}}, ${{ aggqq43g3qg4 }} +const variable = (key) => + new RegExp("\\${{\\s*?" + key + "\\s*?}}", "g"); + + +// default value set in /action.yml +// const root = core.getInput('root', { required: false }); +root = '/tmp/workspace'; + +const templatePath = path.join(__dirname, "gcc_matcher.jsontemplate"); + +const parsed = + fs.readFileSync(templatePath, "ascii") + .replace(variable("BASE"), escapeRegExp(root)); + +const matcherPath = path.join(__dirname, "gcc_matcher.json"); + +fs.writeFileSync(matcherPath, parsed); + +console.log('::add-matcher::' + matcherPath); + +/* for testing */ +exports.escapeRegExp = escapeRegExp +exports.variable = variable; \ No newline at end of file diff --git a/test/unittest.js b/test/unittest.js new file mode 100644 index 0000000..0b586a7 --- /dev/null +++ b/test/unittest.js @@ -0,0 +1,38 @@ +const assert = require('node:assert'); +const test = require('node:test'); +const _testing = require('../src/index'); + +test('regex escaping test', () => { + const escapeRegExp = _testing.escapeRegExp; + + const st = [ + {str: "C:\\Users\\", ok: "C\\:\\\\Users\\\\"}, + {str: "/usr/bin/", ok: "\\/usr\\/bin\\/"}, + {str: "(\\\\d+):", ok: "\\(\\\\\\\\d\\+\\)\\:"} + ]; + + st.forEach( (x) => { + const result = escapeRegExp(x.str); + console.log(result, x.ok); + assert.strictEqual(result, x.ok); + }); +}); + +test('variable regex matching test', () => { + const variable = _testing.variable; + + const expected = [ + {needle: "foo", haystack: "this sentence contains variable ${{foo}}", ok: true}, + {needle: "bar", haystack: "finds \n ${{bar}} \n in multilines", ok: true}, + {needle: "baz", haystack: "${{ baz }}", ok: true}, + {needle: "", haystack: "${{aaa}}", ok: false}, + {needle: "bad", haystack: "{{bad}}", ok: false}, + {needle: "", haystack: "${{}}", ok: true}, + ]; + + expected.forEach( (x) => { + console.log(x); + const match = x.haystack.match(variable(x.needle)); + assert.strictEqual( match !== null, x.ok ); + }); +});