react-native-cache-build-gitlab 1.0.5 → 1.0.7
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/README.md +119 -49
- package/package.json +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/provider-gitlab/artifacts.d.ts +0 -19
- package/dist/provider-gitlab/artifacts.js +0 -106
- package/dist/provider-gitlab/config.d.ts +0 -8
- package/dist/provider-gitlab/config.js +0 -21
- package/dist/provider-gitlab/providerGitlab.d.ts +0 -36
- package/dist/provider-gitlab/providerGitlab.js +0 -78
package/README.md
CHANGED
|
@@ -4,10 +4,13 @@ GitLab Generic Package provider for [RockJS](https://rockjs.dev) with single pac
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
📦 **Single Package Storage**: Stores all native builds (iOS & Android) in a single GitLab Generic Package.
|
|
8
|
+
|
|
9
|
+
🧾 **Fingerprint-based Lookup**: Fast artifact retrieval by filename matching.
|
|
10
|
+
|
|
11
|
+
🤖️ **CI/CD Ready**: Works seamlessly with GitLab CI.
|
|
12
|
+
|
|
13
|
+
🪙 **Cost Effective**: Reduces package registry clutter by grouping artifacts.
|
|
11
14
|
|
|
12
15
|
## Installation
|
|
13
16
|
|
|
@@ -17,56 +20,100 @@ npm install react-native-cache-build-gitlab
|
|
|
17
20
|
yarn add react-native-cache-build-gitlab
|
|
18
21
|
```
|
|
19
22
|
|
|
23
|
+
## ⚠️ Prerequisites & Configuration
|
|
24
|
+
|
|
25
|
+
**Important:** You must configure your project according to the [RockJS documentation](https://www.rockjs.dev/docs/cli/migrating-from-community-cli).
|
|
26
|
+
|
|
27
|
+
Before using this provider, you need to set up authentication. This provider uses `CI_JOB_TOKEN` as the default environment variable for authentication.
|
|
28
|
+
|
|
29
|
+
### **1. Create a Personal Access Token**
|
|
30
|
+
|
|
31
|
+
- Go to **GitLab** → **Edit profile** → **Personal access tokens**.
|
|
32
|
+
- Click **Add new token**.
|
|
33
|
+
- Give the token a name and expiration date (recommended).
|
|
34
|
+
- Select scopes you need (commonly: `read_api`, `read_repository`, `write_repository`).
|
|
35
|
+
- Create the token and copy it now — GitLab shows it only once.
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
### **2. Expose the token as an environment variable**
|
|
40
|
+
|
|
41
|
+
The provider expects the token in the `CI_JOB_TOKEN` environment variable
|
|
42
|
+
|
|
43
|
+
#### Temporary (Current Shell)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
export CI_JOB_TOKEN=glt-abc123...
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Permanent (macOS/Linux - Zsh):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
echo 'export CI_JOB_TOKEN=glt-abc123...' >> ~/.zshrc
|
|
53
|
+
source ~/.zshrc
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Note:** In GitLab CI pipelines, `CI_JOB_TOKEN` is automatically injected, so you don't need to configure it manually there.
|
|
57
|
+
|
|
20
58
|
## Usage
|
|
21
59
|
|
|
22
60
|
In your `rock.config.mjs`:
|
|
23
61
|
|
|
24
62
|
```ts
|
|
25
|
-
import {platformIOS} from "@rock-js/platform-ios";
|
|
26
|
-
import {platformAndroid} from "@rock-js/platform-android";
|
|
27
|
-
import {providerGitLab} from "react-native-cache-build-gitlab";
|
|
28
|
-
import {pluginMetro} from "@rock-js/plugin-metro";
|
|
63
|
+
import { platformIOS } from "@rock-js/platform-ios";
|
|
64
|
+
import { platformAndroid } from "@rock-js/platform-android";
|
|
65
|
+
import { providerGitLab } from "react-native-cache-build-gitlab";
|
|
66
|
+
import { pluginMetro } from "@rock-js/plugin-metro";
|
|
29
67
|
|
|
30
68
|
export default {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
69
|
+
bundler: pluginMetro(),
|
|
70
|
+
platforms: {
|
|
71
|
+
ios: platformIOS(),
|
|
72
|
+
android: platformAndroid(),
|
|
73
|
+
},
|
|
74
|
+
remoteCacheProvider: providerGitLab({
|
|
75
|
+
packageName: "mobile-artifacts",
|
|
76
|
+
registryServer: "https://your-gitlab-instance.com",
|
|
77
|
+
projectId: 1234,
|
|
78
|
+
/*
|
|
79
|
+
* token: process.env.CI_JOB_TOKEN (default)
|
|
80
|
+
* tokenHeader: process.env.CI ? "JOB-TOKEN" : "PRIVATE-TOKEN" (default)
|
|
81
|
+
* */
|
|
82
|
+
}),
|
|
83
|
+
fingerprint: {
|
|
84
|
+
ignorePaths: [
|
|
85
|
+
"ios/Podfile.lock",
|
|
86
|
+
"ios/**/xcuserdata",
|
|
87
|
+
"ios/**/project.pbxproj",
|
|
88
|
+
// Add more paths to ignore as needed
|
|
89
|
+
],
|
|
90
|
+
},
|
|
51
91
|
};
|
|
52
92
|
```
|
|
53
93
|
|
|
54
94
|
## Configuration
|
|
55
95
|
|
|
56
|
-
| Option
|
|
57
|
-
|
|
|
58
|
-
| `packageName`
|
|
59
|
-
| `
|
|
60
|
-
| `projectId`
|
|
61
|
-
| `token`
|
|
62
|
-
|
|
|
63
|
-
| `tokenHeader` | `"JOB-TOKEN" \| "PRIVATE-TOKEN"` | Token type |
|
|
96
|
+
| Option | Type | Description |
|
|
97
|
+
| ---------------- | -------- | ------------------------------------------------------------------------------------------ |
|
|
98
|
+
| `packageName` | `string` | Package name in GitLab Generic Package Registry |
|
|
99
|
+
| `registryServer` | `string` | GitLab instance URL |
|
|
100
|
+
| `projectId` | `number` | GitLab project ID |
|
|
101
|
+
| `token` | `string` | (Optional) Auth token. Defaults to `process.env.CI_JOB_TOKEN` |
|
|
102
|
+
| `tokenHeader` | `string` | (Optional) Auth token header. Defaults to `process.env.CI ? "JOB-TOKEN" : "PRIVATE-TOKEN"` |
|
|
64
103
|
|
|
65
104
|
## How It Works
|
|
66
105
|
|
|
67
106
|
### Upload (CI)
|
|
68
107
|
|
|
69
|
-
|
|
108
|
+
When your CI pipeline runs, you can use a script to upload the build artifacts to the GitLab Package Registry. (See the `example` folder in the repository for the `upload-cache-remote.sh` script).
|
|
109
|
+
|
|
110
|
+

|
|
111
|
+
|
|
112
|
+
### Registry Structure
|
|
113
|
+
|
|
114
|
+
All builds are uploaded to a single package version (e.g., 1.0.0).
|
|
115
|
+
|
|
116
|
+

|
|
70
117
|
|
|
71
118
|
```
|
|
72
119
|
mobile-artifacts@1.0.0/
|
|
@@ -75,13 +122,19 @@ mobile-artifacts@1.0.0/
|
|
|
75
122
|
└── ...
|
|
76
123
|
```
|
|
77
124
|
|
|
78
|
-
### Download (Local
|
|
125
|
+
### Download (Local)
|
|
79
126
|
|
|
80
|
-
When
|
|
127
|
+
When you run `bun rock:run-ios` or `bun rock:run-android`:
|
|
81
128
|
|
|
82
|
-
1.
|
|
83
|
-
2.
|
|
84
|
-
3.
|
|
129
|
+
1. Rock calculates the **project fingerprint**.
|
|
130
|
+
2. The provider searches the GitLab Package for a file containing that fingerprint.
|
|
131
|
+
3. If found, it downloads and extracts the artifact automatically.
|
|
132
|
+
|
|
133
|
+
> Android:
|
|
134
|
+
> 
|
|
135
|
+
|
|
136
|
+
> iOS:
|
|
137
|
+
> 
|
|
85
138
|
|
|
86
139
|
## GitLab CI Example
|
|
87
140
|
|
|
@@ -89,16 +142,33 @@ When running:
|
|
|
89
142
|
build_android_cache:
|
|
90
143
|
stage: build
|
|
91
144
|
script:
|
|
92
|
-
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
145
|
+
- |
|
|
146
|
+
bun run rock:build-android
|
|
147
|
+
|
|
148
|
+
CACHE_DIR="$(ls -1dt .rock/cache/remote-build/${NAME_PREFIX}-* | head -n1 || true)"
|
|
96
149
|
|
|
97
|
-
|
|
150
|
+
if [[ -z "${CACHE_DIR}" || ! -d "${CACHE_DIR}" ]]; then
|
|
151
|
+
echo "No cache output under .rock/cache/remote-build/${NAME_PREFIX}-*"
|
|
152
|
+
exit 1
|
|
153
|
+
fi
|
|
154
|
+
echo "CACHE_DIR=${CACHE_DIR}"
|
|
98
155
|
|
|
99
|
-
|
|
156
|
+
FP="${CACHE_DIR##*-}"
|
|
157
|
+
echo "Fingerprint: ${FP}"
|
|
158
|
+
|
|
159
|
+
if ! compgen -G "${CACHE_DIR}"/*.apk > /dev/null; then
|
|
160
|
+
echo "No .apk found in ${CACHE_DIR}"
|
|
161
|
+
ls -la "${CACHE_DIR}" || true
|
|
162
|
+
exit 1
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
FILE_UPLOAD_NAME="${NAME_PREFIX}-${FP}.zip"
|
|
166
|
+
echo "FILE_UPLOAD_NAME=${FILE_UPLOAD_NAME}"
|
|
167
|
+
|
|
168
|
+
sh scripts/upload-cache-remote.sh "${CACHE_DIR}" "${FILE_UPLOAD_NAME}" android
|
|
169
|
+
```
|
|
100
170
|
|
|
101
|
-
|
|
171
|
+
> **_You can refer to the CI gitlab config in folder example_**
|
|
102
172
|
|
|
103
173
|
## License
|
|
104
174
|
|
package/package.json
CHANGED
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { providerGitLab } from "./provider-gitlab/providerGitlab.js";
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { providerGitLab } from "./provider-gitlab/providerGitlab.js";
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { type RemoteArtifact } from "@rock-js/tools";
|
|
2
|
-
export type GitLabRepoDetails = {
|
|
3
|
-
baseUrl: string;
|
|
4
|
-
projectId: number | string;
|
|
5
|
-
token: string;
|
|
6
|
-
tokenHeader: "PRIVATE-TOKEN" | "JOB-TOKEN";
|
|
7
|
-
packageName: string;
|
|
8
|
-
};
|
|
9
|
-
export type GitLabArtifact = {
|
|
10
|
-
packageId: number;
|
|
11
|
-
fileId: number;
|
|
12
|
-
name: string;
|
|
13
|
-
version: string;
|
|
14
|
-
sizeInBytes: number;
|
|
15
|
-
createdAt: string;
|
|
16
|
-
downloadUrl: string;
|
|
17
|
-
};
|
|
18
|
-
export declare function fetchGitLabArtifactsByName(name: string | undefined, repo: GitLabRepoDetails, limit?: number, version?: string): Promise<GitLabArtifact[]>;
|
|
19
|
-
export declare function deleteGitLabArtifacts(artifacts: GitLabArtifact[], repo: GitLabRepoDetails, artifactNameForLog?: string): Promise<RemoteArtifact[]>;
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { cacheManager, color, colorLink, logger, RockError, } from "@rock-js/tools";
|
|
2
|
-
const PAGE_SIZE = 100;
|
|
3
|
-
function headersFor(repo) {
|
|
4
|
-
return {
|
|
5
|
-
[repo.tokenHeader]: repo.token,
|
|
6
|
-
Accept: "application/json",
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
async function httpJson(url, repo) {
|
|
10
|
-
const res = await fetch(url, { headers: headersFor(repo) });
|
|
11
|
-
if (!res.ok) {
|
|
12
|
-
const body = await res.text().catch(() => "");
|
|
13
|
-
const info = `${res.status} ${res.statusText}${body ? ` — ${body}` : ""}`;
|
|
14
|
-
if (res.status === 401 || res.status === 403) {
|
|
15
|
-
cacheManager.remove("gitlabToken");
|
|
16
|
-
throw new RockError(`GitLab auth failed.\nUpdate token under ${color.bold("remoteCacheProvider")} in ${colorLink("rock.config.mjs")}. Local uses ${color.bold("PRIVATE-TOKEN")}, CI uses ${color.bold("JOB-TOKEN")}.\nURL: ${colorLink(url)}\nError: ${info}`);
|
|
17
|
-
}
|
|
18
|
-
if (res.status === 404) {
|
|
19
|
-
throw new RockError(`GitLab 404.\nCheck baseUrl/projectId/packageName or token perms.\nURL: ${colorLink(url)}`);
|
|
20
|
-
}
|
|
21
|
-
throw new RockError(`GitLab request failed: ${info}`);
|
|
22
|
-
}
|
|
23
|
-
return (await res.json());
|
|
24
|
-
}
|
|
25
|
-
function genericDownloadUrl(repo, packageName, version, fileName) {
|
|
26
|
-
const { baseUrl, projectId } = repo;
|
|
27
|
-
return `${baseUrl}/api/v4/projects/${encodeURIComponent(String(projectId))}/packages/generic/${encodeURIComponent(packageName)}/${encodeURIComponent(version)}/${encodeURIComponent(fileName)}`;
|
|
28
|
-
}
|
|
29
|
-
export async function fetchGitLabArtifactsByName(name, repo, limit, version) {
|
|
30
|
-
if (!repo?.token) {
|
|
31
|
-
throw new RockError("Missing GitLab token. Valid repoDetails.token & tokenHeader pass.");
|
|
32
|
-
}
|
|
33
|
-
const perPage = Math.min(limit ?? PAGE_SIZE, PAGE_SIZE);
|
|
34
|
-
let page = 1;
|
|
35
|
-
const packages = [];
|
|
36
|
-
while (true) {
|
|
37
|
-
const url = `${repo.baseUrl}/api/v4/projects/${encodeURIComponent(String(repo.projectId))}/packages` +
|
|
38
|
-
`?package_type=generic&per_page=${perPage}&page=${page}` +
|
|
39
|
-
(name ? `&package_name=${encodeURIComponent(name)}` : "");
|
|
40
|
-
const chunk = await httpJson(url, repo);
|
|
41
|
-
if (!chunk.length)
|
|
42
|
-
break;
|
|
43
|
-
packages.push(...chunk);
|
|
44
|
-
if (chunk.length < perPage)
|
|
45
|
-
break;
|
|
46
|
-
page += 1;
|
|
47
|
-
}
|
|
48
|
-
const artifacts = [];
|
|
49
|
-
for (const pkg of packages) {
|
|
50
|
-
if (pkg.package_type !== "generic" || !pkg.version)
|
|
51
|
-
continue;
|
|
52
|
-
// Don't filter by version here - we'll filter by filename later
|
|
53
|
-
let fPage = 1;
|
|
54
|
-
while (true) {
|
|
55
|
-
const filesUrl = `${repo.baseUrl}/api/v4/projects/${encodeURIComponent(String(repo.projectId))}` +
|
|
56
|
-
`/packages/${pkg.id}/package_files?per_page=${PAGE_SIZE}&page=${fPage}`;
|
|
57
|
-
const files = await httpJson(filesUrl, repo);
|
|
58
|
-
if (!files.length)
|
|
59
|
-
break;
|
|
60
|
-
for (const file of files) {
|
|
61
|
-
// If version (fingerprint) is provided, filter by filename containing it
|
|
62
|
-
if (version && !file.file_name.includes(version))
|
|
63
|
-
continue;
|
|
64
|
-
artifacts.push({
|
|
65
|
-
packageId: pkg.id,
|
|
66
|
-
fileId: file.id,
|
|
67
|
-
name: pkg.name,
|
|
68
|
-
version: pkg.version,
|
|
69
|
-
sizeInBytes: file.size,
|
|
70
|
-
createdAt: file.created_at,
|
|
71
|
-
downloadUrl: genericDownloadUrl(repo, pkg.name, pkg.version, file.file_name),
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
if (files.length < PAGE_SIZE)
|
|
75
|
-
break;
|
|
76
|
-
fPage += 1;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
artifacts.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
80
|
-
return artifacts;
|
|
81
|
-
}
|
|
82
|
-
export async function deleteGitLabArtifacts(artifacts, repo, artifactNameForLog) {
|
|
83
|
-
const deleted = [];
|
|
84
|
-
try {
|
|
85
|
-
for (const artifact of artifacts) {
|
|
86
|
-
const url = `${repo.baseUrl}/api/v4/projects/${encodeURIComponent(String(repo.projectId))}/packages/${artifact.packageId}/package_files/${artifact.fileId}`;
|
|
87
|
-
const res = await fetch(url, {
|
|
88
|
-
method: "DELETE",
|
|
89
|
-
headers: headersFor(repo),
|
|
90
|
-
});
|
|
91
|
-
if (!res.ok) {
|
|
92
|
-
logger.warn(`Delete failed packageId=${artifact.packageId}, fileId=${artifact.fileId}: ${res.status} ${res.statusText}`);
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
deleted.push({
|
|
96
|
-
name: `${artifact.name}@${artifact.version}`,
|
|
97
|
-
url: artifact.downloadUrl,
|
|
98
|
-
id: String(artifact.fileId),
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
return deleted;
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
throw new RockError(`Failed to delete GitLab artifacts${artifactNameForLog ? ` for "${artifactNameForLog}"` : ""}`, { cause: error });
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { GitLabRepoDetails } from "./artifacts";
|
|
2
|
-
export type DetectGitLabRepoInput = Partial<GitLabRepoDetails> & {
|
|
3
|
-
baseUrl?: string;
|
|
4
|
-
projectId?: number | string;
|
|
5
|
-
token?: string;
|
|
6
|
-
tokenHeader?: "JOB-TOKEN" | "PRIVATE-TOKEN";
|
|
7
|
-
};
|
|
8
|
-
export declare function detectGitLabRepoDetails(override?: DetectGitLabRepoInput): Promise<GitLabRepoDetails>;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { RockError } from "@rock-js/tools";
|
|
2
|
-
export async function detectGitLabRepoDetails(override) {
|
|
3
|
-
const baseUrl = override?.baseUrl;
|
|
4
|
-
const projectId = override?.projectId;
|
|
5
|
-
const token = override?.token;
|
|
6
|
-
const tokenHeader = override?.tokenHeader;
|
|
7
|
-
const packageName = override?.packageName;
|
|
8
|
-
if (!projectId) {
|
|
9
|
-
throw new RockError("Missing GitLab projectId. Set GITLAB_PROJECT_ID or pass in override.");
|
|
10
|
-
}
|
|
11
|
-
if (!token) {
|
|
12
|
-
throw new RockError("Missing GitLab token. Use CI_JOB_TOKEN or GITLAB_TOKEN.");
|
|
13
|
-
}
|
|
14
|
-
return {
|
|
15
|
-
baseUrl,
|
|
16
|
-
projectId,
|
|
17
|
-
token,
|
|
18
|
-
tokenHeader,
|
|
19
|
-
packageName,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { RemoteArtifact, RemoteBuildCache } from "@rock-js/tools";
|
|
2
|
-
import { type GitLabRepoDetails } from "./artifacts.js";
|
|
3
|
-
export declare class GitLabBuildCache implements RemoteBuildCache {
|
|
4
|
-
name: string;
|
|
5
|
-
repoDetails: GitLabRepoDetails | null;
|
|
6
|
-
constructor(config?: {
|
|
7
|
-
baseUrl: string;
|
|
8
|
-
projectId: number | string;
|
|
9
|
-
token?: string;
|
|
10
|
-
tokenHeader?: "JOB-TOKEN" | "PRIVATE-TOKEN";
|
|
11
|
-
packageName: string;
|
|
12
|
-
});
|
|
13
|
-
getRepoDetails(): Promise<GitLabRepoDetails>;
|
|
14
|
-
list({ artifactName, limit, }: {
|
|
15
|
-
artifactName?: string;
|
|
16
|
-
limit?: number;
|
|
17
|
-
}): Promise<RemoteArtifact[]>;
|
|
18
|
-
download({ artifactName, }: {
|
|
19
|
-
artifactName: string;
|
|
20
|
-
}): Promise<Response>;
|
|
21
|
-
delete({ artifactName, limit, skipLatest, }: {
|
|
22
|
-
artifactName: string;
|
|
23
|
-
limit?: number;
|
|
24
|
-
skipLatest?: boolean;
|
|
25
|
-
}): Promise<RemoteArtifact[]>;
|
|
26
|
-
upload(): Promise<RemoteArtifact & {
|
|
27
|
-
getResponse: (buffer: Buffer | ((baseUrl: string) => Buffer), contentType?: string | undefined) => Response;
|
|
28
|
-
}>;
|
|
29
|
-
}
|
|
30
|
-
export declare const providerGitLab: (options?: {
|
|
31
|
-
baseUrl: string;
|
|
32
|
-
projectId: number;
|
|
33
|
-
token?: string;
|
|
34
|
-
tokenHeader?: "PRIVATE-TOKEN" | "JOB-TOKEN";
|
|
35
|
-
packageName: string;
|
|
36
|
-
}) => () => RemoteBuildCache;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { deleteGitLabArtifacts, fetchGitLabArtifactsByName, } from "./artifacts.js";
|
|
2
|
-
import { detectGitLabRepoDetails } from "./config.js";
|
|
3
|
-
function parseRockArtifact(artifactName) {
|
|
4
|
-
if (!artifactName)
|
|
5
|
-
return {};
|
|
6
|
-
const maybe = artifactName.split("-").pop();
|
|
7
|
-
if (/^[a-f0-9]{40}$/.test(maybe))
|
|
8
|
-
return { fingerprint: maybe };
|
|
9
|
-
return {};
|
|
10
|
-
}
|
|
11
|
-
export class GitLabBuildCache {
|
|
12
|
-
name = "GitLab";
|
|
13
|
-
repoDetails = null;
|
|
14
|
-
constructor(config) {
|
|
15
|
-
if (config) {
|
|
16
|
-
const token = config.token ?? process.env.CI_JOB_TOKEN;
|
|
17
|
-
const tokenHeader = config.tokenHeader ?? (process.env.CI ? "JOB-TOKEN" : "PRIVATE-TOKEN");
|
|
18
|
-
if (!token) {
|
|
19
|
-
throw new Error("GitLab token is required. Set CI_JOB_TOKEN (CI) or GITLAB_PRIVATE_TOKEN/PRIVATE_TOKEN (local).");
|
|
20
|
-
}
|
|
21
|
-
this.repoDetails = {
|
|
22
|
-
packageName: config.packageName,
|
|
23
|
-
baseUrl: config.baseUrl,
|
|
24
|
-
projectId: config.projectId,
|
|
25
|
-
token,
|
|
26
|
-
tokenHeader,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async getRepoDetails() {
|
|
31
|
-
if (!this.repoDetails) {
|
|
32
|
-
this.repoDetails = await detectGitLabRepoDetails();
|
|
33
|
-
}
|
|
34
|
-
return this.repoDetails;
|
|
35
|
-
}
|
|
36
|
-
async list({ artifactName, limit, }) {
|
|
37
|
-
const repo = await this.getRepoDetails();
|
|
38
|
-
const { fingerprint } = parseRockArtifact(artifactName);
|
|
39
|
-
const artifacts = await fetchGitLabArtifactsByName(repo.packageName, repo, limit, fingerprint);
|
|
40
|
-
return artifacts.map((artifact) => ({
|
|
41
|
-
name: `${artifact.name}@${artifact.version}`,
|
|
42
|
-
url: artifact.downloadUrl,
|
|
43
|
-
id: `${artifact.packageId}:${artifact.fileId}`,
|
|
44
|
-
}));
|
|
45
|
-
}
|
|
46
|
-
async download({ artifactName, }) {
|
|
47
|
-
const repo = await this.getRepoDetails();
|
|
48
|
-
const { fingerprint } = parseRockArtifact(artifactName);
|
|
49
|
-
if (!fingerprint)
|
|
50
|
-
throw new Error("artifactName is required");
|
|
51
|
-
const list = await fetchGitLabArtifactsByName(repo.packageName, repo, 1, fingerprint);
|
|
52
|
-
if (list.length === 0) {
|
|
53
|
-
throw new Error(`No GitLab artifact found for "${artifactName}"${fingerprint ? ` (version=${fingerprint})` : ""}`);
|
|
54
|
-
}
|
|
55
|
-
const url = list[0].downloadUrl;
|
|
56
|
-
return fetch(url, {
|
|
57
|
-
headers: {
|
|
58
|
-
[repo.tokenHeader]: repo.token,
|
|
59
|
-
"Accept-Encoding": "identity",
|
|
60
|
-
},
|
|
61
|
-
redirect: "follow",
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
async delete({ artifactName, limit, skipLatest, }) {
|
|
65
|
-
const repo = await this.getRepoDetails();
|
|
66
|
-
const { fingerprint } = parseRockArtifact(artifactName);
|
|
67
|
-
const artifacts = await fetchGitLabArtifactsByName(repo.packageName, repo, limit, fingerprint);
|
|
68
|
-
if (artifacts.length === 0) {
|
|
69
|
-
throw new Error(`No GitLab artifact found for "${artifactName}"${fingerprint ? ` (version=${fingerprint})` : ""}`);
|
|
70
|
-
}
|
|
71
|
-
const list = skipLatest ? artifacts.slice(1) : artifacts;
|
|
72
|
-
return deleteGitLabArtifacts(list, repo, artifactName);
|
|
73
|
-
}
|
|
74
|
-
async upload() {
|
|
75
|
-
throw new Error("Uploading via RemoteBuildCache is not yet implemented.");
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export const providerGitLab = (options) => () => new GitLabBuildCache(options);
|