Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ability to specify branches for (any)-file-content rules #293

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ declare class RuleInfo {
fixConfig?: any
policyInfo?: string
policyUrl?: string
sequentialOnly?: boolean
}

declare class FormatResult {
Expand Down
140 changes: 124 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ async function runRuleset(ruleset, targets, fileSystem, dryRun) {
// generate a flat array of axiom string identifiers
/** @ignore @type {string[]} */
let targetArray = []
const sequentialRuleProcessingArrayList = ruleset.filter(
r => r.sequentialOnly
)
if (typeof targets !== 'boolean') {
targetArray = Object.entries(targets)
// restricted to only passed axioms
Expand All @@ -302,26 +305,33 @@ async function runRuleset(ruleset, targets, fileSystem, dryRun) {
.reduce((a, c) => a.concat(c), [])
}
// run the ruleset
ruleset = ruleset.filter(r => !r.sequentialOnly)
const results = ruleset.map(async r => {
// check axioms and enable appropriately
if (r.level === 'off') {
return FormatResult.CreateIgnored(r, 'ignored because level is "off"')
return Promise.resolve(
FormatResult.CreateIgnored(r, 'ignored because level is "off"')
)
}
// filter to only targets with no matches
if (typeof targets !== 'boolean' && r.where && r.where.length) {
const ignoreReasons = shouldRuleRun(targetArray, r.where)
if (ignoreReasons.length > 0) {
return FormatResult.CreateIgnored(
r,
`ignored due to unsatisfied condition(s): "${ignoreReasons.join(
'", "'
)}"`
return Promise.resolve(
FormatResult.CreateIgnored(
r,
`ignored due to unsatisfied condition(s): "${ignoreReasons.join(
'", "'
)}"`
)
)
}
}
// check if the rule file exists
if (!Object.prototype.hasOwnProperty.call(Rules, r.ruleType)) {
return FormatResult.CreateError(r, `${r.ruleType} is not a valid rule`)
return Promise.resolve(
FormatResult.CreateError(r, `${r.ruleType} is not a valid rule`)
)
}
let result
try {
Expand All @@ -330,9 +340,11 @@ async function runRuleset(ruleset, targets, fileSystem, dryRun) {
// run the rule!
result = await ruleFunc(fileSystem, r.ruleConfig)
} catch (e) {
return FormatResult.CreateError(
r,
`${r.ruleType} threw an error: ${e.message}`
return Promise.resolve(
FormatResult.CreateError(
r,
`${r.ruleType} threw an error: ${e.message}`
)
)
}
// generate fix targets
Expand All @@ -341,27 +353,123 @@ async function runRuleset(ruleset, targets, fileSystem, dryRun) {
: []
// if there's no fix or the rule passed, we're done
if (!r.fixType || result.passed) {
return FormatResult.CreateLintOnly(r, result)
return Promise.resolve(FormatResult.CreateLintOnly(r, result))
}
// else run the fix
// check if the rule file exists
if (!Object.prototype.hasOwnProperty.call(Fixes, r.fixType)) {
return FormatResult.CreateError(r, `${r.fixType} is not a valid fix`)
return Promise.resolve(
FormatResult.CreateError(r, `${r.fixType} is not a valid fix`)
)
}
let fixresult
try {
const fixFunc = Fixes[r.fixType]
fixresult = await fixFunc(fileSystem, r.fixConfig, fixTargets, dryRun)
} catch (e) {
return FormatResult.CreateError(
r,
`${r.fixType} threw an error: ${e.message}`
return Promise.resolve(
FormatResult.CreateError(r, `${r.fixType} threw an error: ${e.message}`)
)
}
// all done! return the final format object
return FormatResult.CreateLintAndFix(r, result, fixresult)
return Promise.resolve(FormatResult.CreateLintAndFix(r, result, fixresult))
})

await Promise.all(results)
for (let i = 0; i < sequentialRuleProcessingArrayList.length; i++) {
const r = sequentialRuleProcessingArrayList[i]
// check axioms and enable appropriately
if (r.level === 'off') {
results.push(
Promise.resolve(
FormatResult.CreateIgnored(r, 'ignored because level is "off"')
)
)
continue
}
// filter to only targets with no matches
if (typeof targets !== 'boolean' && r.where && r.where.length) {
const ignoreReasons = shouldRuleRun(targetArray, r.where)
if (ignoreReasons.length > 0) {
results.push(
Promise.resolve(
FormatResult.CreateIgnored(
r,
`ignored due to unsatisfied condition(s): "${ignoreReasons.join(
'", "'
)}"`
)
)
)
continue
}
}
// check if the rule file exists
if (!Object.prototype.hasOwnProperty.call(Rules, r.ruleType)) {
results.push(
Promise.resolve(
FormatResult.CreateError(r, `${r.ruleType} is not a valid rule`)
)
)
continue
}
let result
try {
// load the rule
const ruleFunc = Rules[r.ruleType]
// run the rule!
result = await ruleFunc(fileSystem, r.ruleConfig)
} catch (e) {
results.push(
Promise.resolve(
FormatResult.CreateError(
r,
`${r.ruleType} threw an error: ${e.message}`
)
)
)
continue
}
// generate fix targets
const fixTargets = !result.passed
? result.targets.filter(t => !t.passed && t.path).map(t => t.path)
: []
// if there's no fix or the rule passed, we're done
if (!r.fixType || result.passed) {
results.push(Promise.resolve(FormatResult.CreateLintOnly(r, result)))
continue
}
// else run the fix
// check if the rule file exists
if (!Object.prototype.hasOwnProperty.call(Fixes, r.fixType)) {
results.push(
Promise.resolve(
FormatResult.CreateError(r, `${r.fixType} is not a valid fix`)
)
)
continue
}
let fixresult
try {
const fixFunc = Fixes[r.fixType]()
fixresult = await fixFunc(fileSystem, r.fixConfig, fixTargets, dryRun)
} catch (e) {
results.push(
Promise.resolve(
FormatResult.CreateError(
r,
`${r.fixType} threw an error: ${e.message}`
)
)
)
continue
}
// all done! return the final format object
results.push(
Promise.resolve(FormatResult.CreateLintAndFix(r, result, fixresult))
)
}

return Promise.all(results)
}

Expand Down
3 changes: 2 additions & 1 deletion lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ function parseConfig(config) {
cfg.fix && cfg.fix.type,
cfg.fix && cfg.fix.options,
cfg.policyInfo,
cfg.policyUrl
cfg.policyUrl,
cfg.sequentialOnly
)
)
}
Expand Down
4 changes: 3 additions & 1 deletion lib/ruleinfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class RuleInfo {
fixType,
fixConfig,
policyInfo,
policyUrl
policyUrl,
sequentialOnly
) {
this.name = name
this.level = level
Expand All @@ -37,6 +38,7 @@ class RuleInfo {
if (fixConfig) this.fixConfig = fixConfig
if (policyInfo) this.policyInfo = policyInfo
if (policyUrl) this.policyUrl = policyUrl
if (sequentialOnly) this.sequentialOnly = sequentialOnly
}
}

Expand Down
6 changes: 6 additions & 0 deletions rules/file-contents-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"type": "array",
"items": { "type": "string" }
},
"branches": {
"type": "array",
"items": { "type": "string" },
"default": []
},
"skipDefaultBranch": { "type": "boolean", "default": false },
"content": { "type": "string" },
"flags": { "type": "string" },
"human-readable-content": { "type": "string" },
Expand Down
Loading