@backstage-community/plugin-jfrog-artifactory 1.23.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +36 -1
- package/config.d.ts +15 -0
- package/dist/api/index.esm.js +30 -8
- package/dist/api/index.esm.js.map +1 -1
- package/dist/components/JfrogArtifactoryDashboardPage/JfrogArtifactoryDashboardPage.esm.js +11 -2
- package/dist/components/JfrogArtifactoryDashboardPage/JfrogArtifactoryDashboardPage.esm.js.map +1 -1
- package/dist/components/JfrogArtifactoryRepository/JfrogArtifactoryRepository.esm.js +10 -2
- package/dist/components/JfrogArtifactoryRepository/JfrogArtifactoryRepository.esm.js.map +1 -1
- package/dist/components/useJfrogArtifactoryAppData.esm.js +4 -2
- package/dist/components/useJfrogArtifactoryAppData.esm.js.map +1 -1
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
### Dependencies
|
|
2
2
|
|
|
3
|
+
## 1.24.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 908af36: Added configuration fields to sort, filter and pagination for artifacts.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 699c87f: Updated dependency `cross-fetch` to `4.1.0`.
|
|
12
|
+
|
|
3
13
|
## 1.23.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -14,9 +14,19 @@ The Jfrog Artifactory plugin displays information about your container images wi
|
|
|
14
14
|
yarn workspace app add @backstage-community/plugin-jfrog-artifactory
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
1.
|
|
17
|
+
1. Configure the Artifactory plugin in the `app-config.yaml` file as follows:
|
|
18
18
|
|
|
19
19
|
```yaml title="app-config.yaml"
|
|
20
|
+
# JFrog Artifactory configuration
|
|
21
|
+
jfrogArtifactory:
|
|
22
|
+
proxyPath: /jfrog-artifactory/api
|
|
23
|
+
# Sort field for artifacts: 'NAME_SEMVER' or 'MODIFIED'
|
|
24
|
+
sortField: 'MODIFIED'
|
|
25
|
+
# Repository filter for artifacts
|
|
26
|
+
repoFilter: '*-prod-federated'
|
|
27
|
+
# Maximum number of artifacts to fetch per request (default: 100)
|
|
28
|
+
pageLimit: 100
|
|
29
|
+
|
|
20
30
|
proxy:
|
|
21
31
|
endpoints:
|
|
22
32
|
'/jfrog-artifactory/api':
|
|
@@ -27,6 +37,16 @@ The Jfrog Artifactory plugin displays information about your container images wi
|
|
|
27
37
|
secure: true
|
|
28
38
|
```
|
|
29
39
|
|
|
40
|
+
- The `sortField` option determines how artifacts are sorted in the UI:
|
|
41
|
+
- `NAME_SEMVER`: Sort by semantic version name (default if not specified)
|
|
42
|
+
- `MODIFIED`: Sort by last modified date
|
|
43
|
+
|
|
44
|
+
- The `repoFilter` option determines which repositories to include when displaying artifacts. It supports wildcard patterns (e.g., '\*-prod-federated') to filter artifacts by repository name. When specified, only artifacts from repositories matching this pattern will be shown.
|
|
45
|
+
|
|
46
|
+
- The `pageLimit`: Controls the maximum number of artifacts fetched per request (default: 100)
|
|
47
|
+
- **Note**: This setting limits the number of artifacts displayed in the UI
|
|
48
|
+
- If you have many artifacts, consider increasing this value to see more results
|
|
49
|
+
|
|
30
50
|
If you have multiple instances of artifactory supported, you can set up multiple proxy target paths as follows:
|
|
31
51
|
|
|
32
52
|
```yaml title="app-config.yaml"
|
|
@@ -75,8 +95,23 @@ proxy:
|
|
|
75
95
|
# if your app supports multiple artifactory instances,
|
|
76
96
|
# you'll need to specify the instance proxy target path your image belongs to
|
|
77
97
|
'jfrog-artifactory/target-proxy': '/<PROXY-TARGET>' # e.g. `/jfrog-instance1` from the example above
|
|
98
|
+
# Optional: filter repositories by name pattern
|
|
99
|
+
'jfrog-artifactory/repo-filter': '*-prod-federated'
|
|
78
100
|
```
|
|
79
101
|
|
|
102
|
+
The annotations serve the following purposes:
|
|
103
|
+
|
|
104
|
+
- `jfrog-artifactory/image-name`: Specifies the image name to display in the Artifactory tab
|
|
105
|
+
- `jfrog-artifactory/target-proxy`: Specifies which Artifactory instance to use (for multiple instances)
|
|
106
|
+
- `jfrog-artifactory/repo-filter`: Optional filter to limit which repositories are displayed for this entity (supports wildcard patterns)
|
|
107
|
+
|
|
108
|
+
**Note on repository filtering:**
|
|
109
|
+
|
|
110
|
+
- The `jfrog-artifactory/repo-filter` annotation provides entity-specific repository filtering
|
|
111
|
+
- If the annotation is not defined for an entity, the global `repoFilter` from app-config.yaml will be used
|
|
112
|
+
- Entity-level annotation takes precedence over the global configuration
|
|
113
|
+
- This allows for both global defaults and per-entity customization
|
|
114
|
+
|
|
80
115
|
## For users
|
|
81
116
|
|
|
82
117
|
### Using the Jfrog Artifactory plugin in Backstage
|
package/config.d.ts
CHANGED
|
@@ -21,5 +21,20 @@ export interface Config {
|
|
|
21
21
|
* @visibility frontend
|
|
22
22
|
*/
|
|
23
23
|
proxyPath?: string;
|
|
24
|
+
/**
|
|
25
|
+
* The sort field for the Jfrog Artifactory instance.
|
|
26
|
+
* @visibility frontend
|
|
27
|
+
*/
|
|
28
|
+
sortField?: string;
|
|
29
|
+
/**
|
|
30
|
+
* The repository filter of the Jfrog Artifactory instance.
|
|
31
|
+
* @visibility frontend
|
|
32
|
+
*/
|
|
33
|
+
repoFilter?: string;
|
|
34
|
+
/**
|
|
35
|
+
* The page limit of the Jfrog Artifactory instance.
|
|
36
|
+
* @visibility frontend
|
|
37
|
+
*/
|
|
38
|
+
pageLimit?: number;
|
|
24
39
|
};
|
|
25
40
|
}
|
package/dist/api/index.esm.js
CHANGED
|
@@ -35,19 +35,41 @@ class JfrogArtifactoryApiClient {
|
|
|
35
35
|
}
|
|
36
36
|
return await response.json();
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
getSortField() {
|
|
39
|
+
const sortField = this.configApi.getOptionalString(
|
|
40
|
+
"jfrogArtifactory.sortField"
|
|
41
|
+
);
|
|
42
|
+
if (sortField === "MODIFIED" || sortField === "NAME_SEMVER") {
|
|
43
|
+
return sortField;
|
|
44
|
+
}
|
|
45
|
+
return "NAME_SEMVER";
|
|
46
|
+
}
|
|
47
|
+
getRepoFilter() {
|
|
48
|
+
return this.configApi.getOptionalString("jfrogArtifactory.repoFilter");
|
|
49
|
+
}
|
|
50
|
+
getPageLimit() {
|
|
51
|
+
return this.configApi.getOptionalNumber("jfrogArtifactory.pageLimit") || 100;
|
|
52
|
+
}
|
|
53
|
+
async getTags(image, target, repoFilter) {
|
|
39
54
|
const proxyUrl = await this.getBaseUrl(target);
|
|
55
|
+
const filter = {
|
|
56
|
+
packageId: `docker://${image}`,
|
|
57
|
+
name: "*",
|
|
58
|
+
ignorePreRelease: false
|
|
59
|
+
};
|
|
60
|
+
const repositoryFilter = repoFilter || this.getRepoFilter();
|
|
61
|
+
if (repositoryFilter) {
|
|
62
|
+
filter.repositoriesIn = {
|
|
63
|
+
name: repositoryFilter
|
|
64
|
+
};
|
|
65
|
+
}
|
|
40
66
|
const tagQuery = {
|
|
41
67
|
query: "query ($filter: VersionFilter!, $first: Int, $orderBy: VersionOrder) { versions (filter: $filter, first: $first, orderBy: $orderBy) { edges { node { name, created, modified, package { id }, repos { name, type, leadFilePath }, licenses { name, source }, size, stats { downloadCount }, vulnerabilities { critical, high, medium, low, info, unknown, skipped }, files { name, lead, size, md5, sha1, sha256, mimeType } } } } }",
|
|
42
68
|
variables: {
|
|
43
|
-
filter
|
|
44
|
-
|
|
45
|
-
name: "*",
|
|
46
|
-
ignorePreRelease: false
|
|
47
|
-
},
|
|
48
|
-
first: 100,
|
|
69
|
+
filter,
|
|
70
|
+
first: this.getPageLimit(),
|
|
49
71
|
orderBy: {
|
|
50
|
-
field:
|
|
72
|
+
field: this.getSortField(),
|
|
51
73
|
direction: "DESC"
|
|
52
74
|
}
|
|
53
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ConfigApi,\n createApiRef,\n DiscoveryApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\n\nimport { TagsResponse } from '../types';\n\nconst DEFAULT_PROXY_PATH = '/jfrog-artifactory/api';\n\nexport interface JfrogArtifactoryApiV1 {\n getTags(
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ConfigApi,\n createApiRef,\n DiscoveryApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\n\nimport { TagsResponse } from '../types';\n\nconst DEFAULT_PROXY_PATH = '/jfrog-artifactory/api';\n\nexport interface JfrogArtifactoryApiV1 {\n getTags(\n image: string,\n target?: string,\n repoFilter?: string,\n ): Promise<TagsResponse>;\n}\n\nexport const jfrogArtifactoryApiRef = createApiRef<JfrogArtifactoryApiV1>({\n id: 'plugin.jfrog-artifactory.service',\n});\n\nexport type Options = {\n discoveryApi: DiscoveryApi;\n configApi: ConfigApi;\n identityApi: IdentityApi;\n};\n\nexport class JfrogArtifactoryApiClient implements JfrogArtifactoryApiV1 {\n // @ts-ignore\n private readonly discoveryApi: DiscoveryApi;\n\n private readonly configApi: ConfigApi;\n\n private readonly identityApi: IdentityApi;\n\n constructor(options: Options) {\n this.discoveryApi = options.discoveryApi;\n this.configApi = options.configApi;\n this.identityApi = options.identityApi;\n }\n\n private async getBaseUrl(target?: string) {\n const proxyPath =\n this.configApi.getOptionalString('jfrogArtifactory.proxyPath') ||\n DEFAULT_PROXY_PATH;\n return `${await this.discoveryApi.getBaseUrl('proxy')}${\n target ?? proxyPath\n }`;\n }\n\n private async fetcher(url: string, query: string) {\n const { token: idToken } = await this.identityApi.getCredentials();\n const response = await fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n ...(idToken && { Authorization: `Bearer ${idToken}` }),\n },\n method: 'POST',\n body: query,\n });\n if (!response.ok) {\n throw new Error(\n `failed to fetch data, status ${response.status}: ${response.statusText}`,\n );\n }\n return await response.json();\n }\n\n private getSortField(): string {\n const sortField = this.configApi.getOptionalString(\n 'jfrogArtifactory.sortField',\n );\n\n // Only allow valid sort fields\n if (sortField === 'MODIFIED' || sortField === 'NAME_SEMVER') {\n return sortField;\n }\n\n // Default to NAME_SEMVER if not specified or invalid\n return 'NAME_SEMVER';\n }\n\n private getRepoFilter(): string | undefined {\n return this.configApi.getOptionalString('jfrogArtifactory.repoFilter');\n }\n\n private getPageLimit(): number {\n return (\n this.configApi.getOptionalNumber('jfrogArtifactory.pageLimit') || 100\n );\n }\n\n async getTags(image: string, target?: string, repoFilter?: string) {\n const proxyUrl = await this.getBaseUrl(target);\n\n const filter: any = {\n packageId: `docker://${image}`,\n name: '*',\n ignorePreRelease: false,\n };\n\n const repositoryFilter = repoFilter || this.getRepoFilter();\n if (repositoryFilter) {\n filter.repositoriesIn = {\n name: repositoryFilter,\n };\n }\n\n const tagQuery = {\n query:\n 'query ($filter: VersionFilter!, $first: Int, $orderBy: VersionOrder) { versions (filter: $filter, first: $first, orderBy: $orderBy) { edges { node { name, created, modified, package { id }, repos { name, type, leadFilePath }, licenses { name, source }, size, stats { downloadCount }, vulnerabilities { critical, high, medium, low, info, unknown, skipped }, files { name, lead, size, md5, sha1, sha256, mimeType } } } } }',\n variables: {\n filter,\n first: this.getPageLimit(),\n orderBy: {\n field: this.getSortField(),\n direction: 'DESC',\n },\n },\n };\n\n return (await this.fetcher(\n `${proxyUrl}/metadata/api/v1/query`,\n JSON.stringify(tagQuery),\n )) as TagsResponse;\n }\n}\n"],"names":[],"mappings":";;AAwBA,MAAM,kBAAqB,GAAA,wBAAA;AAUpB,MAAM,yBAAyB,YAAoC,CAAA;AAAA,EACxE,EAAI,EAAA;AACN,CAAC;AAQM,MAAM,yBAA2D,CAAA;AAAA;AAAA,EAErD,YAAA;AAAA,EAEA,SAAA;AAAA,EAEA,WAAA;AAAA,EAEjB,YAAY,OAAkB,EAAA;AAC5B,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA;AACzB,IAAA,IAAA,CAAK,cAAc,OAAQ,CAAA,WAAA;AAAA;AAC7B,EAEA,MAAc,WAAW,MAAiB,EAAA;AACxC,IAAA,MAAM,SACJ,GAAA,IAAA,CAAK,SAAU,CAAA,iBAAA,CAAkB,4BAA4B,CAC7D,IAAA,kBAAA;AACF,IAAO,OAAA,CAAA,EAAG,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,OAAO,CAAC,CACnD,EAAA,MAAA,IAAU,SACZ,CAAA,CAAA;AAAA;AACF,EAEA,MAAc,OAAQ,CAAA,GAAA,EAAa,KAAe,EAAA;AAChD,IAAA,MAAM,EAAE,KAAO,EAAA,OAAA,KAAY,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA;AACjE,IAAM,MAAA,QAAA,GAAW,MAAM,KAAA,CAAM,GAAK,EAAA;AAAA,MAChC,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA,kBAAA;AAAA,QAChB,GAAI,OAAW,IAAA,EAAE,aAAe,EAAA,CAAA,OAAA,EAAU,OAAO,CAAG,CAAA;AAAA,OACtD;AAAA,MACA,MAAQ,EAAA,MAAA;AAAA,MACR,IAAM,EAAA;AAAA,KACP,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAgC,6BAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,OACzE;AAAA;AAEF,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC7B,EAEQ,YAAuB,GAAA;AAC7B,IAAM,MAAA,SAAA,GAAY,KAAK,SAAU,CAAA,iBAAA;AAAA,MAC/B;AAAA,KACF;AAGA,IAAI,IAAA,SAAA,KAAc,UAAc,IAAA,SAAA,KAAc,aAAe,EAAA;AAC3D,MAAO,OAAA,SAAA;AAAA;AAIT,IAAO,OAAA,aAAA;AAAA;AACT,EAEQ,aAAoC,GAAA;AAC1C,IAAO,OAAA,IAAA,CAAK,SAAU,CAAA,iBAAA,CAAkB,6BAA6B,CAAA;AAAA;AACvE,EAEQ,YAAuB,GAAA;AAC7B,IAAA,OACE,IAAK,CAAA,SAAA,CAAU,iBAAkB,CAAA,4BAA4B,CAAK,IAAA,GAAA;AAAA;AAEtE,EAEA,MAAM,OAAA,CAAQ,KAAe,EAAA,MAAA,EAAiB,UAAqB,EAAA;AACjE,IAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,UAAA,CAAW,MAAM,CAAA;AAE7C,IAAA,MAAM,MAAc,GAAA;AAAA,MAClB,SAAA,EAAW,YAAY,KAAK,CAAA,CAAA;AAAA,MAC5B,IAAM,EAAA,GAAA;AAAA,MACN,gBAAkB,EAAA;AAAA,KACpB;AAEA,IAAM,MAAA,gBAAA,GAAmB,UAAc,IAAA,IAAA,CAAK,aAAc,EAAA;AAC1D,IAAA,IAAI,gBAAkB,EAAA;AACpB,MAAA,MAAA,CAAO,cAAiB,GAAA;AAAA,QACtB,IAAM,EAAA;AAAA,OACR;AAAA;AAGF,IAAA,MAAM,QAAW,GAAA;AAAA,MACf,KACE,EAAA,saAAA;AAAA,MACF,SAAW,EAAA;AAAA,QACT,MAAA;AAAA,QACA,KAAA,EAAO,KAAK,YAAa,EAAA;AAAA,QACzB,OAAS,EAAA;AAAA,UACP,KAAA,EAAO,KAAK,YAAa,EAAA;AAAA,UACzB,SAAW,EAAA;AAAA;AACb;AACF,KACF;AAEA,IAAA,OAAQ,MAAM,IAAK,CAAA,OAAA;AAAA,MACjB,GAAG,QAAQ,CAAA,sBAAA,CAAA;AAAA,MACX,IAAA,CAAK,UAAU,QAAQ;AAAA,KACzB;AAAA;AAEJ;;;;"}
|
|
@@ -5,8 +5,17 @@ import { useJfrogArtifactoryAppData } from '../useJfrogArtifactoryAppData.esm.js
|
|
|
5
5
|
|
|
6
6
|
const JfrogArtifactoryDashboardPage = () => {
|
|
7
7
|
const { entity } = useEntity();
|
|
8
|
-
const { imageName, targetProxy } = useJfrogArtifactoryAppData({
|
|
9
|
-
|
|
8
|
+
const { imageName, targetProxy, repoFilter } = useJfrogArtifactoryAppData({
|
|
9
|
+
entity
|
|
10
|
+
});
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
JfrogArtifactoryRepository,
|
|
13
|
+
{
|
|
14
|
+
image: imageName,
|
|
15
|
+
target: targetProxy,
|
|
16
|
+
repoFilter
|
|
17
|
+
}
|
|
18
|
+
);
|
|
10
19
|
};
|
|
11
20
|
|
|
12
21
|
export { JfrogArtifactoryDashboardPage };
|
package/dist/components/JfrogArtifactoryDashboardPage/JfrogArtifactoryDashboardPage.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfrogArtifactoryDashboardPage.esm.js","sources":["../../../src/components/JfrogArtifactoryDashboardPage/JfrogArtifactoryDashboardPage.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useEntity } from '@backstage/plugin-catalog-react';\n\nimport { JfrogArtifactoryRepository } from '../JfrogArtifactoryRepository';\nimport { useJfrogArtifactoryAppData } from '../useJfrogArtifactoryAppData';\n\nexport const JfrogArtifactoryDashboardPage = () => {\n const { entity } = useEntity();\n const { imageName, targetProxy } = useJfrogArtifactoryAppData({
|
|
1
|
+
{"version":3,"file":"JfrogArtifactoryDashboardPage.esm.js","sources":["../../../src/components/JfrogArtifactoryDashboardPage/JfrogArtifactoryDashboardPage.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useEntity } from '@backstage/plugin-catalog-react';\n\nimport { JfrogArtifactoryRepository } from '../JfrogArtifactoryRepository';\nimport { useJfrogArtifactoryAppData } from '../useJfrogArtifactoryAppData';\n\nexport const JfrogArtifactoryDashboardPage = () => {\n const { entity } = useEntity();\n const { imageName, targetProxy, repoFilter } = useJfrogArtifactoryAppData({\n entity,\n });\n\n return (\n <JfrogArtifactoryRepository\n image={imageName}\n target={targetProxy}\n repoFilter={repoFilter}\n />\n );\n};\n"],"names":[],"mappings":";;;;;AAoBO,MAAM,gCAAgC,MAAM;AACjD,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAA,MAAM,EAAE,SAAA,EAAW,WAAa,EAAA,UAAA,KAAe,0BAA2B,CAAA;AAAA,IACxE;AAAA,GACD,CAAA;AAED,EACE,uBAAA,GAAA;AAAA,IAAC,0BAAA;AAAA,IAAA;AAAA,MACC,KAAO,EAAA,SAAA;AAAA,MACP,MAAQ,EAAA,WAAA;AAAA,MACR;AAAA;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -19,7 +19,11 @@ const useLocalStyles = makeStyles({
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
|
-
function JfrogArtifactoryRepository({
|
|
22
|
+
function JfrogArtifactoryRepository({
|
|
23
|
+
image,
|
|
24
|
+
target,
|
|
25
|
+
repoFilter
|
|
26
|
+
}) {
|
|
23
27
|
const jfrogArtifactoryClient = useApi(jfrogArtifactoryApiRef);
|
|
24
28
|
const classes = useStyles();
|
|
25
29
|
const localClasses = useLocalStyles();
|
|
@@ -27,7 +31,11 @@ function JfrogArtifactoryRepository({ image, target }) {
|
|
|
27
31
|
const [edges, setEdges] = useState([]);
|
|
28
32
|
const titleprop = t("page.title", { image });
|
|
29
33
|
const { loading } = useAsync(async () => {
|
|
30
|
-
const tagsResponse = await jfrogArtifactoryClient.getTags(
|
|
34
|
+
const tagsResponse = await jfrogArtifactoryClient.getTags(
|
|
35
|
+
image,
|
|
36
|
+
target,
|
|
37
|
+
repoFilter
|
|
38
|
+
);
|
|
31
39
|
setEdges(tagsResponse.data.versions.edges);
|
|
32
40
|
return tagsResponse;
|
|
33
41
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfrogArtifactoryRepository.esm.js","sources":["../../../src/components/JfrogArtifactoryRepository/JfrogArtifactoryRepository.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState, useMemo } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { Link, Progress, Table } from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { Box, Chip, makeStyles } from '@material-ui/core';\n\nimport { jfrogArtifactoryApiRef } from '../../api';\nimport { Edge } from '../../types';\nimport { getColumns, useStyles } from './tableHeading';\nimport { formatByteSize, formatDate } from '../../utils';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nconst useLocalStyles = makeStyles({\n chip: {\n margin: 0,\n marginRight: '.2em',\n height: '1.5em',\n '& > span': {\n padding: '.3em',\n },\n },\n});\n\nexport function JfrogArtifactoryRepository({
|
|
1
|
+
{"version":3,"file":"JfrogArtifactoryRepository.esm.js","sources":["../../../src/components/JfrogArtifactoryRepository/JfrogArtifactoryRepository.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState, useMemo } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { Link, Progress, Table } from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { Box, Chip, makeStyles } from '@material-ui/core';\n\nimport { jfrogArtifactoryApiRef } from '../../api';\nimport { Edge } from '../../types';\nimport { getColumns, useStyles } from './tableHeading';\nimport { formatByteSize, formatDate } from '../../utils';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nconst useLocalStyles = makeStyles({\n chip: {\n margin: 0,\n marginRight: '.2em',\n height: '1.5em',\n '& > span': {\n padding: '.3em',\n },\n },\n});\n\nexport function JfrogArtifactoryRepository({\n image,\n target,\n repoFilter,\n}: RepositoryProps) {\n const jfrogArtifactoryClient = useApi(jfrogArtifactoryApiRef);\n const classes = useStyles();\n const localClasses = useLocalStyles();\n const { t } = useTranslation();\n const [edges, setEdges] = useState<Edge[]>([]);\n const titleprop = t('page.title', { image } as Record<string, string>);\n\n const { loading } = useAsync(async () => {\n const tagsResponse = await jfrogArtifactoryClient.getTags(\n image,\n target,\n repoFilter,\n );\n\n setEdges(tagsResponse.data.versions.edges);\n\n return tagsResponse;\n });\n\n const columns = useMemo(() => getColumns(t), [t]);\n\n if (loading) {\n return <Progress />;\n }\n\n const data = edges?.map((edge: Edge) => {\n const shortHash = edge.node.files\n .find(manifest => manifest.name === 'manifest.json')\n ?.sha256.substring(0, 12);\n return {\n name: edge.node.name,\n last_modified: formatDate(edge.node.modified),\n size: formatByteSize(Number(edge.node.size)),\n manifest_digest: (\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <Chip label={t('manifest.sha256')} className={localClasses.chip} />\n {shortHash}\n </Box>\n ),\n repositories:\n `${edge.node.repos.length}` +\n ' | ' +\n `${edge.node.repos.map(repo => repo.name).join('| ')}`,\n };\n });\n\n return (\n <div style={{ border: '1px solid #ddd' }}>\n <Table\n title={titleprop}\n options={{ paging: true, padding: 'dense' }}\n data={data}\n columns={columns}\n emptyContent={\n <div className={classes.empty}>\n {t('table.emptyContent.message')} \n <Link to=\"https://backstage.io/\">\n {t('table.emptyContent.learnMore')}\n </Link>\n </div>\n }\n localization={{\n toolbar: { searchPlaceholder: t('table.searchPlaceholder') },\n pagination: { labelRowsSelect: t('table.labelRowsSelect') },\n }}\n />\n </div>\n );\n}\n\ninterface RepositoryProps {\n image: string;\n target?: string;\n repoFilter?: string;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME = "jfrog-artifactory/image-name";
|
|
2
2
|
const JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY = "jfrog-artifactory/target-proxy";
|
|
3
|
+
const JFROG_ARTIFACTORY_ANNOTATION_REPO_FILTER = "jfrog-artifactory/repo-filter";
|
|
3
4
|
const useJfrogArtifactoryAppData = ({ entity }) => {
|
|
4
5
|
const imageName = entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME] ?? "";
|
|
5
6
|
const targetProxy = entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY];
|
|
7
|
+
const repoFilter = entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_REPO_FILTER];
|
|
6
8
|
if (!imageName) {
|
|
7
9
|
throw new Error("'Jfrog Artifactory' annotations are missing");
|
|
8
10
|
}
|
|
9
|
-
return { imageName, targetProxy };
|
|
11
|
+
return { imageName, targetProxy, repoFilter };
|
|
10
12
|
};
|
|
11
13
|
|
|
12
|
-
export { JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME, JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY, useJfrogArtifactoryAppData };
|
|
14
|
+
export { JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME, JFROG_ARTIFACTORY_ANNOTATION_REPO_FILTER, JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY, useJfrogArtifactoryAppData };
|
|
13
15
|
//# sourceMappingURL=useJfrogArtifactoryAppData.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useJfrogArtifactoryAppData.esm.js","sources":["../../src/components/useJfrogArtifactoryAppData.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Entity } from '@backstage/catalog-model';\n\nexport const JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME =\n 'jfrog-artifactory/image-name';\n\nexport const JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY =\n 'jfrog-artifactory/target-proxy';\n\nexport const useJfrogArtifactoryAppData = ({ entity }: { entity: Entity }) => {\n const imageName =\n entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME] ??\n '';\n\n const targetProxy =\n entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY];\n\n if (!imageName) {\n throw new Error(\"'Jfrog Artifactory' annotations are missing\");\n }\n return { imageName, targetProxy };\n};\n"],"names":[],"mappings":"AAiBO,MAAM,uCACX,GAAA;AAEK,MAAM,yCACX,GAAA;AAEK,MAAM,0BAA6B,GAAA,CAAC,EAAE,MAAA,EAAiC,KAAA;AAC5E,EAAA,MAAM,SACJ,GAAA,MAAA,EAAQ,QAAS,CAAA,WAAA,GAAc,uCAAuC,CACtE,IAAA,EAAA;AAEF,EAAA,MAAM,WACJ,GAAA,MAAA,EAAQ,QAAS,CAAA,WAAA,GAAc,yCAAyC,CAAA;AAE1E,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAM,MAAA,IAAI,MAAM,6CAA6C,CAAA;AAAA;AAE/D,EAAO,OAAA,EAAE,
|
|
1
|
+
{"version":3,"file":"useJfrogArtifactoryAppData.esm.js","sources":["../../src/components/useJfrogArtifactoryAppData.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Entity } from '@backstage/catalog-model';\n\nexport const JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME =\n 'jfrog-artifactory/image-name';\n\nexport const JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY =\n 'jfrog-artifactory/target-proxy';\n\nexport const JFROG_ARTIFACTORY_ANNOTATION_REPO_FILTER =\n 'jfrog-artifactory/repo-filter';\n\nexport const useJfrogArtifactoryAppData = ({ entity }: { entity: Entity }) => {\n const imageName =\n entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_IMAGE_NAME] ??\n '';\n\n const targetProxy =\n entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_TARGET_PROXY];\n\n const repoFilter =\n entity?.metadata.annotations?.[JFROG_ARTIFACTORY_ANNOTATION_REPO_FILTER];\n\n if (!imageName) {\n throw new Error(\"'Jfrog Artifactory' annotations are missing\");\n }\n return { imageName, targetProxy, repoFilter };\n};\n"],"names":[],"mappings":"AAiBO,MAAM,uCACX,GAAA;AAEK,MAAM,yCACX,GAAA;AAEK,MAAM,wCACX,GAAA;AAEK,MAAM,0BAA6B,GAAA,CAAC,EAAE,MAAA,EAAiC,KAAA;AAC5E,EAAA,MAAM,SACJ,GAAA,MAAA,EAAQ,QAAS,CAAA,WAAA,GAAc,uCAAuC,CACtE,IAAA,EAAA;AAEF,EAAA,MAAM,WACJ,GAAA,MAAA,EAAQ,QAAS,CAAA,WAAA,GAAc,yCAAyC,CAAA;AAE1E,EAAA,MAAM,UACJ,GAAA,MAAA,EAAQ,QAAS,CAAA,WAAA,GAAc,wCAAwC,CAAA;AAEzE,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAM,MAAA,IAAI,MAAM,6CAA6C,CAAA;AAAA;AAE/D,EAAO,OAAA,EAAE,SAAW,EAAA,WAAA,EAAa,UAAW,EAAA;AAC9C;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-jfrog-artifactory",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"main": "./dist/index.esm.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -66,13 +66,15 @@
|
|
|
66
66
|
"react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
+
"@axe-core/playwright": "^4.11.0",
|
|
69
70
|
"@backstage/cli": "^0.34.5",
|
|
70
71
|
"@backstage/dev-utils": "^1.1.17",
|
|
71
72
|
"@backstage/test-utils": "^1.7.13",
|
|
73
|
+
"@playwright/test": "^1.57.0",
|
|
72
74
|
"@testing-library/jest-dom": "6.9.1",
|
|
73
75
|
"@testing-library/react": "14.3.1",
|
|
74
76
|
"@types/luxon": "^3",
|
|
75
|
-
"cross-fetch": "4.
|
|
77
|
+
"cross-fetch": "4.1.0",
|
|
76
78
|
"react-router-dom": "^6.26.2"
|
|
77
79
|
},
|
|
78
80
|
"files": [
|