diff --git a/.github/workflows/validate-pubnub-yml.yml b/.github/workflows/validate-pubnub-yml.yml new file mode 100644 index 0000000..9fad8d7 --- /dev/null +++ b/.github/workflows/validate-pubnub-yml.yml @@ -0,0 +1,21 @@ +name: validate-pubnub-yml +on: [push] + +jobs: + build: + name: Validate PubNub yml + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: '12.x' + - name: Install dependencies + run: | + npm install ajv@6.12.6 + npm install yaml@1.10.0 + npm install node-fetch@2.6.1 + npm install chalk@2.4.2 + - name: Validate + run: GITHUB_TOKEN=${{ secrets.GH_TOKEN }} node ./.github/workflows/validate-yml.js diff --git a/.github/workflows/validate-yml.js b/.github/workflows/validate-yml.js new file mode 100644 index 0000000..2fc52cb --- /dev/null +++ b/.github/workflows/validate-yml.js @@ -0,0 +1,104 @@ +const YAML = require('yaml'); +const Ajv = require('ajv'); +const fetch = require('node-fetch'); +const fs = require('fs'); +const chalk = require('chalk'); + +const ghToken = process.env.GITHUB_TOKEN; +const ghHeaders = { + 'User-Agent': 'sdk-bot', + Authorization: 'token ' + ghToken, + Accept: 'application/vnd.github.v3.raw', +}; + +const sdkReposJSONBranch = 'develop'; +let sdkReposJSONPath = + 'http://api.github.com/repos/pubnub/documentation-resources/contents/website-common/tools/build/sdk-repos.json?ref=' + + sdkReposJSONBranch; +startExecution(sdkReposJSONPath); + +async function startExecution(sdkReposJSONPath) { + var sdkRepos = await requestGetFromGithub(sdkReposJSONPath); + var sdkReposAndFeatureMappingArray = parseReposAndFeatureMapping(sdkRepos); + var schemaText = await requestGetFromGithub( + sdkReposAndFeatureMappingArray[2] + ); + + schema = JSON.parse(schemaText); + var yaml = fs.readFileSync('.pubnub.yml', 'utf8'); + + if (yaml != null) { + yml = YAML.parse(yaml); + var ajv = new Ajv({ schemaId: 'id', verbose: true, allErrors: true }); + const validate = ajv.compile(schema); + const valid = validate(yml); + if (validate.errors != null) { + console.log(chalk.cyan('===================================')); + console.log(chalk.red(yml['version'] + ' validation errors...')); + console.log(chalk.cyan('===================================')); + console.log(validate.errors); + console.log(chalk.cyan('===================================')); + var result = { code: 1, repo: yml['version'], msg: 'validation errors' }; + printResult(result); + process.exit(1); + } else { + var result = { code: 0, repo: yml['version'], msg: 'validation pass' }; + printResult(result); + } + } else { + var result = { code: 1, repo: 'yml null', msg: 'validation errors' }; + printResult(result); + process.exit(1); + } +} + +function printResult(result) { + var str = result.repo + ', ' + result.msg; + if (result.code === 0) { + console.log(chalk.green(str) + ', Code: ' + result.code); + } else { + console.log(chalk.red(str) + ', Code: ' + result.code); + } +} + +async function requestGetFromGithub(url) { + try { + const response = await fetch(url, { + headers: ghHeaders, + method: 'get', + }); + if (response.status == 200) { + const json = await response.text(); + return json; + } else { + console.error( + chalk.red('res.status: ' + response.status + '\n URL: ' + url) + ); + return null; + } + } catch (error) { + console.error( + chalk.red('requestGetFromGithub: ' + error + '\n URL: ' + url) + ); + return null; + } +} + +function parseReposAndFeatureMapping(body) { + if (body != null) { + var sdkRepos = JSON.parse(body); + var locations = sdkRepos['locations']; + if (locations != null) { + var sdkURLs = locations['sdks']; + var featureMappingURL = locations['featureMapping']; + var pubnubYAMLSchemaURL = locations['pubnubYAMLSchema']; + return [sdkURLs, featureMappingURL, pubnubYAMLSchemaURL]; + } else { + console.log(chalk.red('response locations null')); + return null; + } + } else { + console.log(chalk.red('response body null')); + return null; + } +}