POC - JS-601 - Publish RSPEC as an npm package
This commit is contained in:
parent
8586551b59
commit
77f34c3a7b
60
.github/workflows/release.yml
vendored
Normal file
60
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
id-token: write # required for SonarSource/vault-action-wrapper
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||||
|
RELEASE_NAME: ${{ github.event.release.name }}
|
||||||
|
BUILD_NAME: 'rspec'
|
||||||
|
ARTIFACTORY_REPOSITORY_NAME: 'sonarsource-npm-public-releases'
|
||||||
|
steps:
|
||||||
|
- name: Fetch the secrets
|
||||||
|
id: secrets
|
||||||
|
uses: SonarSource/vault-action-wrapper@v3
|
||||||
|
with:
|
||||||
|
secrets:
|
||||||
|
development/artifactory/token/SonarSource-rspec-promoter access_token | promoter_access_token;
|
||||||
|
development/kv/data/npmjs sonartech_npm_token | npm_token;
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
|
||||||
|
- name: Setup the registries
|
||||||
|
run: |
|
||||||
|
npm config set //registry.npmjs.org/:_authToken=${{ fromJSON(steps.secrets.outputs.vault).npm_token }}
|
||||||
|
npm config set //repox.jfrog.io/artifactory/api/npm/:_authToken=${{ fromJSON(steps.secrets.outputs.vault).promoter_access_token }}
|
||||||
|
|
||||||
|
- name: Build the package
|
||||||
|
run: |
|
||||||
|
(cd rspec-tools && npm i)
|
||||||
|
VERSION=${RELEASE_TAG} node rspec-tools/build-package.mjs
|
||||||
|
cp LICENSE build
|
||||||
|
|
||||||
|
- name: Install JFrog CLI
|
||||||
|
uses: SonarSource/jfrog-setup-wrapper@v3
|
||||||
|
|
||||||
|
- name: Publish the package to Artifactory
|
||||||
|
run: |
|
||||||
|
jfrog config add repox --url https://repox.jfrog.io --access-token ${{ fromJSON(steps.secrets.outputs.vault).promoter_access_token }}
|
||||||
|
jfrog config use repox
|
||||||
|
jfrog npm-config --repo-resolve npm --repo-deploy $ARTIFACTORY_REPOSITORY_NAME
|
||||||
|
cd build
|
||||||
|
jfrog npm publish --build-name $BUILD_NAME --build-number $RELEASE_TAG --dry-run
|
||||||
|
jfrog rt build-add-git $BUILD_NAME $RELEASE_TAG
|
||||||
|
jfrog rt build-publish --dry-run $BUILD_NAME $RELEASE_TAG
|
||||||
|
jfrog rt build-promote --dry-run --status released $BUILD_NAME $RELEASE_TAG $ARTIFACTORY_REPOSITORY_NAME
|
||||||
|
|
||||||
|
- name: Publish the package to npm
|
||||||
|
run: |
|
||||||
|
cd build
|
||||||
|
[ ${{ github.event.release.prerelease }} == true ] && TAG="next" || TAG="latest"
|
||||||
|
npm publish --tag=$TAG --access=public --dry-run
|
170
rspec-tools/build-package.mjs
Normal file
170
rspec-tools/build-package.mjs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import {readdirSync, readFileSync, existsSync, writeFileSync, mkdirSync, rmSync} from "node:fs";
|
||||||
|
import {join} from "node:path";
|
||||||
|
import createASCIIDoctor from "asciidoctor";
|
||||||
|
|
||||||
|
const asciiDoctor = createASCIIDoctor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef BaseRuleRepresentation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RuleRepresentation
|
||||||
|
* @property {string} title
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Metadata
|
||||||
|
* @property {string} documentation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Rule
|
||||||
|
* @property {string} name
|
||||||
|
* @property {string} language
|
||||||
|
* @property {string} title
|
||||||
|
* @property {string} type
|
||||||
|
* @property {Metadata} metadata
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} directoryPath
|
||||||
|
* @return {Array<{
|
||||||
|
* rule: Rule;
|
||||||
|
* metadata: Metadata;
|
||||||
|
* }>}
|
||||||
|
*/
|
||||||
|
const readDirectory = (directoryPath) => {
|
||||||
|
const entries = readdirSync(directoryPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} rulePath
|
||||||
|
* @param {string} name
|
||||||
|
* @return {Array<{
|
||||||
|
* rule: Rule;
|
||||||
|
* metadata: Metadata;
|
||||||
|
* }>}
|
||||||
|
*/
|
||||||
|
const processRulePath = (rulePath, name) => {
|
||||||
|
/**
|
||||||
|
* @type {BaseRuleRepresentation}
|
||||||
|
*/
|
||||||
|
const baseRuleRepresentation = JSON.parse(readFileSync(join(rulePath, 'metadata.json'), "utf-8"));
|
||||||
|
|
||||||
|
const languageEntries = readdirSync(join(rulePath), {
|
||||||
|
withFileTypes: true
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Array<Rule>}
|
||||||
|
*/
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
languageEntries.forEach((languageEntry) => {
|
||||||
|
if (languageEntry.isDirectory() && languageEntry.name === "javascript") {
|
||||||
|
const languagePath = join(rulePath, languageEntry.name);
|
||||||
|
const metadataPath = join(languagePath, 'metadata.json');
|
||||||
|
|
||||||
|
if (existsSync(metadataPath)) {
|
||||||
|
/**
|
||||||
|
* @type {RuleRepresentation}
|
||||||
|
*/
|
||||||
|
const ruleRepresentation = {
|
||||||
|
...baseRuleRepresentation,
|
||||||
|
...JSON.parse(readFileSync(metadataPath, "utf-8"))
|
||||||
|
};
|
||||||
|
|
||||||
|
const documentationPath = join(languagePath, 'rule.adoc');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
let documentation;
|
||||||
|
|
||||||
|
if (existsSync(documentationPath)) {
|
||||||
|
documentation = readFileSync(documentationPath, "utf-8");
|
||||||
|
|
||||||
|
documentation = asciiDoctor.convert(documentation, {
|
||||||
|
base_dir: languagePath,
|
||||||
|
safe: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
rule: {
|
||||||
|
name,
|
||||||
|
language: languageEntry.name,
|
||||||
|
...ruleRepresentation
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
documentation
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
const rulePath = join(directoryPath, entry);
|
||||||
|
|
||||||
|
results.push(...processRulePath(rulePath, entry));
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rules = readDirectory('rules');
|
||||||
|
|
||||||
|
const moduleContent = `const registry = new Map([
|
||||||
|
${rules.map((rule) => {
|
||||||
|
return `['${rule.rule.language}/${rule.rule.name}', ${JSON.stringify(rule)}]`
|
||||||
|
})}
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const getRules = () => {
|
||||||
|
return [...registry.values()].map((entry) => entry.rule);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMetadata = (rule) => {
|
||||||
|
const entry = registry.get(rule.language + '/' + rule.name);
|
||||||
|
|
||||||
|
return entry.metadata;
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
|
||||||
|
rmSync('build', {
|
||||||
|
force: true,
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
|
||||||
|
mkdirSync('build', {});
|
||||||
|
|
||||||
|
writeFileSync('build/index.mjs', moduleContent, {});
|
||||||
|
|
||||||
|
writeFileSync('build/index.d.ts', `export type Metadata = {
|
||||||
|
readonly documentation: string;
|
||||||
|
};
|
||||||
|
export type Rule = {
|
||||||
|
readonly language: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly title: string;
|
||||||
|
readonly type: string;
|
||||||
|
readonly defaultQualityProfiles: Array<string>;
|
||||||
|
readonly status: "ready" | "deprecated" | "closed";
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare const getRules: () => Array<Rule>;
|
||||||
|
export declare const getMetadata: (rule: Rule) => Metadata;
|
||||||
|
`, {});
|
||||||
|
|
||||||
|
writeFileSync('build/package.json', JSON.stringify({
|
||||||
|
main: "index.mjs",
|
||||||
|
types: "index.d.ts",
|
||||||
|
name: "@sonar/rspec",
|
||||||
|
version: process.env.VERSION || "SNAPSHOT"
|
||||||
|
}));
|
5
rspec-tools/package.json
Normal file
5
rspec-tools/package.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"asciidoctor": "^3.0.4"
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user