Skip to content

Commit dddb29a

Browse files
authored
Merge pull request #18 from abstracta/feature/support-artifact-name-patterns
Support artifact name patterns
2 parents dae0448 + 78cafc4 commit dddb29a

7 files changed

Lines changed: 155 additions & 49 deletions

File tree

README.md

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ request to the target repository.
1717

1818
The action requires the following inputs:
1919

20-
| Input | Description | Required | Default |
21-
| ---------------------- | -------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------------- |
22-
| `token` | GitHub token used for authentication to perform API operations such as fetching assets and creating PRs. | Yes | - |
23-
| `forked-repository` | URL of your forked repository used to send the PR from. | Yes | - |
24-
| `plugin-id` | Registered ID for identifying the plugin in the JMeter Plugins repository. | Yes | - |
25-
| `plugin-artifact-name` | Prefix of the plugin artifact name used to identify the JAR file in the GitHub release. | Yes | - |
26-
| `changes` | Release note line describing the update. | Yes | - |
27-
| `ignore-dependencies` | Comma-separated prefixes of dependencies to ignore in the release metadata. | No | - |
28-
| `upstream-repository` | URL of the target JMeter Plugins repository to send the PR to. | No | `https://github.com/undera/jmeter-plugins.git` |
20+
| Input | Description | Required | Default |
21+
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------------- |
22+
| `token` | GitHub token used for authentication to perform API operations such as fetching assets and creating PRs. | Yes | - |
23+
| `forked-repository` | URL of your forked repository used to send the PR from. | Yes | - |
24+
| `plugin-id` | Registered ID for identifying the plugin in the JMeter Plugins repository. | Yes | - |
25+
| `plugin-artifact-name` | Prefix of the plugin artifact name used to identify the JAR file in the GitHub release. | Yes | - |
26+
| `changes` | Release note line describing the update. | Yes | - |
27+
| `ignore-dependencies` | Comma-separated prefixes of dependencies to ignore in the release metadata. | No | - |
28+
| `upstream-repository` | URL of the target JMeter Plugins repository to send the PR to. | No | `https://github.com/undera/jmeter-plugins.git` |
29+
| `artifact-version-extraction-patterns` | New line separated (YAML Multiline) of regular expression patterns to extract the version from artifact names. The first capturing group is treated as the version; the remaining part is used to infer the artifact name. | No | - |
2930

3031
## Outputs
3132

@@ -62,6 +63,8 @@ jobs:
6263
plugin-id: example-plugin-id
6364
changes: ${{ inputs.changes }}
6465
token: ${{ secrets.GITHUB_TOKEN }}
66+
artifact-version-extraction-patterns: |
67+
example-lib-(.*)
6568
6669
- name: Print Pull Request URL
6770
run: echo ${{ steps.publish-plugin.outputs.pull_request }}
@@ -90,3 +93,46 @@ jobs:
9093
- Customize ignore-dependencies if some libraries should not be included in the release metadata.
9194
- Field `"depends"` of the release JSON object is grabbed from the latest release.
9295
- Desire of updates requires a manual modification over the PR
96+
97+
### In depth
98+
99+
#### artifact-version-extraction-patterns
100+
101+
The action uses by default a lazy approach when it comes to generate the lib version and artifact
102+
name to be impacted in the JMeter Plugins repository definition.
103+
104+
In case your plugin has a library labeled with a nomenclature `library-0.3-jdk-8.jar` by default the
105+
plugin will consider as artifact name `library-0.3-jdk` and version `8` which isn't entirely correct
106+
for all scenarios.
107+
108+
> In above example the artifact name is `library` and the version is `0.3-jdk-8`.
109+
110+
The property configuration for above scenario will be:
111+
112+
```yaml
113+
- name: Run Publish JMeter Plugin Action
114+
id: publish-plugin
115+
uses: abstracta/jmeter-plugin-publish-action@main
116+
with:
117+
. # other
118+
. # properties
119+
. # here
120+
artifact-version-extraction-patterns: |
121+
library-(.*)
122+
```
123+
124+
In that way the resultant release will be:
125+
126+
```json
127+
{
128+
"1.0.1": {
129+
"changes": "A new release",
130+
"downloadUrl": "https://example.com/your-plugin.jar",
131+
"libs": {
132+
"library>=0.3-jdk-8": "https://example.com/library-0.3-jdk-8.jar"
133+
}
134+
}
135+
}
136+
```
137+
138+
> Instead of `"library-0.3-jdk>=8"`

__tests__/args.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe('Arguments', () => {
4646
expect(args.pluginID).toBe('plugin-123')
4747
expect(args.upstreamRepository).toBe('upstream/repo')
4848
expect(args.changes).toBe('some changes')
49-
expect(args.ingoreDependencies).toEqual(['dep1', 'dep2'])
49+
expect(args.ignoreDependencies).toEqual(['dep1', 'dep2'])
5050
expect(args.githubToken).toBe('github-token')
5151
})
5252

action.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ inputs:
2020
release'
2121
required: true
2222
plugin-id:
23-
description: 'Registered ID for identifing the plugin in jmeter-plugins'
23+
description: 'Registered ID for identifying the plugin in jmeter-plugins'
2424
required: true
2525
token:
2626
description: 'Github token (PAT) used to fetch assets from latest release and open the PR'
@@ -33,6 +33,11 @@ inputs:
3333
"Prefix of dependencies separated by commas, which won't be taken into consideration at
3434
jmeter-plugins release but are present in github release"
3535
required: false
36+
version-extraction-patterns:
37+
description:
38+
'Regular expression patterns to extract the version from artifact names for unconventional
39+
library version patterns'
40+
required: false
3641

3742
outputs:
3843
pull_request:

dist/index.js

Lines changed: 37 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/args.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,23 @@ export class Arguments {
77
upstreamRepository: string
88
githubToken: string
99
changes: string
10-
ingoreDependencies: string[]
10+
ignoreDependencies: string[]
11+
versionPatterns: string[]
12+
1113
constructor() {
1214
this.forkedRepository = this.getValidatedInput('forked-repository')
1315
this.pluginArtifactName = this.getValidatedInput('plugin-artifact-name')
1416
this.pluginID = this.getValidatedInput('plugin-id')
1517
this.upstreamRepository = this.getInputOrDefault(
1618
'upstream-repository',
17-
//Added default value since locally seems to not take the defaul value
19+
//Added default value since locally seems to not take the default value
1820
//defined in action.yaml
1921
'https://github.com/undera/jmeter-plugins.git'
2022
)
2123
this.changes = this.getValidatedInput('changes')
22-
this.ingoreDependencies = getInput('ignore-dependencies').split(',')
24+
this.ignoreDependencies = getInput('ignore-dependencies').split(',')
2325
this.githubToken = this.getGithubToken()
26+
this.versionPatterns = getInput('artifact-version-extraction-patterns').split('\n')
2427
}
2528

2629
private getValidatedInput(input: string): string {

src/release-builder.ts

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,28 @@ import { readdir, readFile } from 'fs/promises'
44
import type { Plugin, PluginVersion } from './jmeter-plugins.d.js'
55
import type { Asset } from './github.js'
66

7+
declare type ArtifactInfo = {
8+
artifactName: string
9+
version: string
10+
}
11+
712
export class ReleaseBuilder {
813
PLUGINS_REPOSITORY_FILE_PATH = 'jmeter-plugins/site/dat/repo/'
914
args: Arguments
1015
assets: Asset[]
16+
1117
constructor(args: Arguments, assets: Asset[]) {
1218
this.args = args
1319
this.assets = assets
1420
}
1521

1622
async build(): Promise<PluginVersion> {
17-
const newPluginVersion: PluginVersion = {
23+
return {
1824
changes: `${this.args.changes}`,
1925
downloadUrl: this.getPluginDownloadUrl(),
2026
libs: this.buildLibs(),
2127
depends: await this.buildDependsOn(),
2228
}
23-
return newPluginVersion
2429
}
2530

2631
private getPluginDownloadUrl(): string {
@@ -42,7 +47,7 @@ export class ReleaseBuilder {
4247
.filter(asset => !asset.name.startsWith(this.args.pluginArtifactName))
4348
.filter(
4449
asset =>
45-
!this.args.ingoreDependencies.some(ignore => ignore && asset.name.startsWith(ignore))
50+
!this.args.ignoreDependencies.some(ignore => ignore && asset.name.startsWith(ignore))
4651
)
4752
.forEach(asset => {
4853
const { libKey, url } = this.buildLibKeyAndUrl(asset)
@@ -52,26 +57,53 @@ export class ReleaseBuilder {
5257
}
5358

5459
private buildLibKeyAndUrl(asset: Asset): { libKey: string; url: string } {
55-
const { artifactName, version } = ReleaseBuilder.dissectArtifactName(asset.name)
56-
const libKey = `${artifactName}>=${version}`
60+
const artifactInfo: ArtifactInfo = ReleaseBuilder.extractArtifactAndVersion(
61+
asset.name,
62+
this.args.versionPatterns
63+
)
64+
const libKey = `${artifactInfo.artifactName}>=${artifactInfo.version}`
5765
const url: string = asset.browser_download_url
5866
return { libKey, url }
5967
}
6068

61-
private static dissectArtifactName(name: string): {
62-
artifactName: string
63-
version: string
64-
} {
65-
const baseName = name.endsWith('.jar') ? name.slice(0, -4) : name
66-
const parts = baseName.split('-')
67-
const version = parts.pop()
68-
const artifactName = parts.join('-')
69+
private static extractArtifactAndVersion(name: string, regexes: string[]): ArtifactInfo {
70+
const baseName = this.stripJarExtension(name)
6971

70-
if (artifactName && version) {
71-
return { artifactName, version }
72-
} else {
73-
throw Error(`Not possible to extract version and name from ${name}`)
72+
for (const pattern of regexes) {
73+
const version = this.extractVersion(baseName, pattern)
74+
if (version && baseName.includes(version)) {
75+
const artifactName = this.inferArtifactName(baseName, version)
76+
return { artifactName, version }
77+
}
7478
}
79+
80+
return this.fallbackExtraction(baseName)
81+
}
82+
83+
private static stripJarExtension(name: string): string {
84+
return name.endsWith('.jar') ? name.slice(0, -4) : name
85+
}
86+
87+
private static extractVersion(baseName: string, pattern: string): string | undefined {
88+
const regex = new RegExp(pattern)
89+
const match = regex.exec(baseName)
90+
return match?.[1]
91+
}
92+
93+
private static inferArtifactName(baseName: string, version: string): string {
94+
const versionIndex = baseName.indexOf(version)
95+
96+
const before = baseName.slice(0, versionIndex)
97+
const after = baseName.slice(versionIndex + version.length)
98+
99+
return (before + after).replace(/[-_.]+$/, '').replace(/^[-_.]+/, '')
100+
}
101+
102+
private static fallbackExtraction(baseName: string): ArtifactInfo {
103+
const parts = baseName.split('-')
104+
const version = parts.pop() ?? ''
105+
const artifactName = parts.join('-')
106+
return { artifactName, version }
75107
}
76108

77109
async findFilePluginRepository(): Promise<string> {

0 commit comments

Comments
 (0)