feat: advanced pattern matching support (#1260)

This commit is contained in:
Simon Lecoq
2022-10-16 21:27:29 -04:00
committed by GitHub
parent 948ec35697
commit 4d3b694343
12 changed files with 127 additions and 15 deletions

View File

@@ -170,9 +170,25 @@ metadata.plugin = async function({__plugins, __templates, name, logger}) {
logger(`metrics/inputs > failed to decode uri : ${value}`) logger(`metrics/inputs > failed to decode uri : ${value}`)
value = defaulted value = defaulted
} }
const separators = {"comma-separated": ",", "space-separated": " "} const separators = {"comma-separated": ",", "space-separated": " ", "newline-separated": "\n"}
const separator = separators[[format].flat().filter(s => s in separators)[0]] ?? "," const formats = [format, "comma-separated"].flat(Infinity).filter(s => s in separators)
return value.split(separator).map(v => replacer(v).toLocaleLowerCase()).filter(v => Array.isArray(values) ? values.includes(v) : true).filter(v => v) let parsed = [], used = "comma-separated"
for (const separation of formats) {
parsed = value
.split(separators[separation])
.map(v => replacer(v).toLocaleLowerCase())
.filter(v => Array.isArray(values) ? values.includes(v) : true)
.filter(v => v)
//Conditional below serves as auto-detection when multiple formats are provided
//To force a specific format one should use the separator as the first character
//so that the parsed.length is greater than 1 (empty values are filtered anyways)
if (parsed.length > 1) {
used = separation
break
}
}
logger(`metrics/inputs > used ${used} format to decode ${value}`)
return parsed
} }
//String //String
case "string": { case "string": {
@@ -625,7 +641,7 @@ metadata.to = {
yaml(key, {name = ""} = {}) { yaml(key, {name = ""} = {}) {
const parts = [] const parts = []
if (key !== "enabled") if (key !== "enabled")
parts.unshift(key.replaceAll(".", "_")) parts.unshift(key.replace(/\./g, "_"))
if (name) if (name)
parts.unshift((name === "base") ? name : `plugin_${name}`) parts.unshift((name === "base") ? name : `plugin_${name}`)
return parts.join("_") return parts.join("_")

View File

@@ -391,9 +391,36 @@ export const filters = {
} }
user = (user ?? repository.split("/")[0]).toLocaleLowerCase() user = (user ?? repository.split("/")[0]).toLocaleLowerCase()
repo = (repo ?? repository.split("/")[1]).toLocaleLowerCase() repo = (repo ?? repository.split("/")[1]).toLocaleLowerCase()
const handle = `${user}/${repo}`
let include = true
//Advanced pattern matching
if (patterns[0] === "@use.patterns") {
if (debug)
console.debug(`metrics/filters/repo > ${repo} > using advanced pattern matching`)
const options = {nocase:true}
for (let pattern of patterns) {
if (pattern.startsWith("#"))
continue
let action = false
if ((pattern.startsWith("+"))||(pattern.startsWith("-"))) {
action = pattern.charAt(0) === "+"
pattern = pattern.substring(1)
}
if (minimatch(handle, pattern, options)) {
if (debug)
console.debug(`metrics/filters/repo > ${repo} matches ${action ? "including" : "excluding"} pattern ${pattern}`)
include = action
}
}
}
//Basic pattern matching //Basic pattern matching
const include = (!patterns.includes(repo)) && (!patterns.includes(`${user}/${repo}`)) else {
if (debug)
console.debug(`metrics/filters/repo > ${repo} > using basic pattern matching`)
include = (!patterns.includes(repo)) && (!patterns.includes(handle))
}
if (debug) if (debug)
console.debug(`metrics/filters/repo > filter ${repo} (${include ? "included" : "excluded"})`) console.debug(`metrics/filters/repo > filter ${repo} (${include ? "included" : "excluded"})`)
return include return include

View File

@@ -65,7 +65,9 @@ inputs:
description: | description: |
Skipped repositories Skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
inherits: repositories_skipped inherits: repositories_skipped

View File

@@ -115,7 +115,9 @@ inputs:
description: | description: |
Default skipped repositories Default skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
global: yes global: yes

View File

@@ -62,7 +62,9 @@ inputs:
description: | description: |
Skipped repositories Skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
inherits: repositories_skipped inherits: repositories_skipped

View File

@@ -57,6 +57,60 @@ Content can be manually ordered using `config_order` option.
> The handles to use for each plugin and sections is based on the [`partials/_.json`](/source/templates/classic/partials/_.json) of the template. > The handles to use for each plugin and sections is based on the [`partials/_.json`](/source/templates/classic/partials/_.json) of the template.
> It may not necessarily be the plugin id (e.g. `base.header`, `base.activity+community`, `base.repositories`, etc.). > It may not necessarily be the plugin id (e.g. `base.header`, `base.activity+community`, `base.repositories`, etc.).
## 🔕 Skipping repositories in plugins
Some plugins support a `plugin_*_skipped` option which is used to skipped repositories from result. It inherits the global option [`repositories_skipped`](/source/plugins/base/README.md#repositories_skipped) which makes it easier to ignore repositories from all plugins at once.
These options support two different syntaxes:
### Basic pattern matching
Skip repositories by:
- using their full handle (e.g. `user/repo`)
- using only their name (e.g. `repo`)
- *in this case, the owner may be implicitly set to current `user` option*
*Example: skipping repositories with basic pattern matching*
```yml
repositories_skipped: my-repo, user/my-repo
```
> 💡 Either comma or newlines can be used to separate basic patterns
### Advanced pattern matching
To enable advanced pattern matching to skip repositories, include `@use.patterns` at the beginning of the option value.
Skip repositories by writing file-glob patterns, with any of the supported operation:
- `#` to write comments
- `-` to exclude repositories
- *the `-` is implicit and may be omitted from excluding patterns*
- `+` to include back repositories
> *metrics* use [isaacs/minimatch](https://github.com/isaacs/minimatch) as its file-glob matcher
*Example: skipping repositories with basic advanced matching*
```yml
repositories_skipped: |
@use.patterns
# Skip a specific repository (both patterns are equivalent)
user/repo
-user/repo
# Skip repositories matching a given pattern
user/repo-*
{user1, user2, user3}/*
# Include back a previously skipped repository
org/repo
+org/include-this-repo
```
> Unlike basic pattern matching, patterns are always tested against the full repository handle (the user will not be implicitly added)
> ⚠️ As patterns may contain commas, be sure to use newlines rather than commas as separator to ensure patterns are correctly parsed
## 🪛 Using presets ## 🪛 Using presets
It is possible to reuse the same configuration across different repositories and workflows using configuration presets. It is possible to reuse the same configuration across different repositories and workflows using configuration presets.

View File

@@ -138,8 +138,7 @@ inputs:
Some templates may not support all options Some templates may not support all options
type: array type: array
default: css, xml default: css, xml
format: format: comma-separated
- comma-separated
values: values:
- css - css
- xml - xml

View File

@@ -33,7 +33,9 @@ inputs:
description: | description: |
Skipped repositories Skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
inherits: repositories_skipped inherits: repositories_skipped

View File

@@ -34,7 +34,9 @@ inputs:
description: | description: |
Skipped repositories Skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
inherits: repositories_skipped inherits: repositories_skipped

View File

@@ -24,7 +24,9 @@ inputs:
description: | description: |
Skipped repositories Skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
inherits: repositories_skipped inherits: repositories_skipped

View File

@@ -35,7 +35,9 @@ inputs:
description: | description: |
Skipped repositories Skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
inherits: repositories_skipped inherits: repositories_skipped

View File

@@ -23,7 +23,9 @@ inputs:
description: | description: |
Skipped repositories Skipped repositories
type: array type: array
format: comma-separated format:
- newline-separated
- comma-separated
default: "" default: ""
example: my-repo-1, my-repo-2, owner/repo-3, ... example: my-repo-1, my-repo-2, owner/repo-3, ...
inherits: repositories_skipped inherits: repositories_skipped