@ticatec/omniflow-github 1.0.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.
Files changed (34) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/README_CN.md +93 -0
  4. package/dist/artifacts/GitHubContainerPublisher.d.ts +16 -0
  5. package/dist/artifacts/GitHubContainerPublisher.d.ts.map +1 -0
  6. package/dist/artifacts/GitHubContainerPublisher.js +47 -0
  7. package/dist/artifacts/GitHubContainerPublisher.js.map +1 -0
  8. package/dist/artifacts/GitHubMavenPublisher.d.ts +25 -0
  9. package/dist/artifacts/GitHubMavenPublisher.d.ts.map +1 -0
  10. package/dist/artifacts/GitHubMavenPublisher.js +186 -0
  11. package/dist/artifacts/GitHubMavenPublisher.js.map +1 -0
  12. package/dist/artifacts/GitHubNpmPublisher.d.ts +21 -0
  13. package/dist/artifacts/GitHubNpmPublisher.d.ts.map +1 -0
  14. package/dist/artifacts/GitHubNpmPublisher.js +49 -0
  15. package/dist/artifacts/GitHubNpmPublisher.js.map +1 -0
  16. package/dist/artifacts/GitHubReleasePublisher.d.ts +31 -0
  17. package/dist/artifacts/GitHubReleasePublisher.d.ts.map +1 -0
  18. package/dist/artifacts/GitHubReleasePublisher.js +192 -0
  19. package/dist/artifacts/GitHubReleasePublisher.js.map +1 -0
  20. package/dist/client/GitHubClient.d.ts +76 -0
  21. package/dist/client/GitHubClient.d.ts.map +1 -0
  22. package/dist/client/GitHubClient.js +170 -0
  23. package/dist/client/GitHubClient.js.map +1 -0
  24. package/dist/index.d.ts +29 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +38 -0
  27. package/dist/index.js.map +1 -0
  28. package/package.json +48 -0
  29. package/src/artifacts/GitHubContainerPublisher.ts +54 -0
  30. package/src/artifacts/GitHubMavenPublisher.ts +238 -0
  31. package/src/artifacts/GitHubNpmPublisher.ts +66 -0
  32. package/src/artifacts/GitHubReleasePublisher.ts +238 -0
  33. package/src/client/GitHubClient.ts +242 -0
  34. package/src/index.ts +54 -0
@@ -0,0 +1,192 @@
1
+ import { promises as fs } from 'fs';
2
+ import path from 'path';
3
+ import crypto from 'crypto';
4
+ import { BasePublisher } from '@ticatec/omniflow-artifact';
5
+ import { GitHubClient } from '../client/GitHubClient.js';
6
+ /**
7
+ * GitHub Releases (Generic Artifact / Asset) Publisher.
8
+ *
9
+ * Publishes arbitrary binary artifacts, distribution tarballs (.tar.gz),
10
+ * or zip files to GitHub Releases under the specified version tag.
11
+ */
12
+ export class GitHubReleasePublisher extends BasePublisher {
13
+ id = 'github-release';
14
+ name = 'GitHub Releases';
15
+ platform = 'github';
16
+ artifactType = 'generic';
17
+ priority = 20;
18
+ detect(registry) {
19
+ if (registry.type !== 'generic' && registry.type !== 'archive' && registry.type !== 'release') {
20
+ return false;
21
+ }
22
+ const regName = (registry.name || '').toLowerCase();
23
+ if (regName === 'github' || regName === 'github-release' || regName.startsWith('github-')) {
24
+ return true;
25
+ }
26
+ const server = (registry.server || '').toLowerCase();
27
+ try {
28
+ const parsed = new URL(server.includes('://') ? server : `https://${server}`);
29
+ return GitHubClient.isGitHubHost(parsed.hostname);
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ buildTargetRef(artifact, registry) {
36
+ const version = artifact.tags && artifact.tags.length > 0 ? artifact.tags[0] : 'v1.0.0';
37
+ const tagName = version.startsWith('v') || /^\d/.test(version) ? version : `v${version}`;
38
+ const filename = artifact.source ? path.basename(artifact.source) : artifact.name;
39
+ try {
40
+ const { owner, repo } = this.resolveOwnerRepo(registry);
41
+ return `${owner}/${repo}@${tagName}#${filename}`;
42
+ }
43
+ catch {
44
+ return `${artifact.name}@${tagName}#${filename}`;
45
+ }
46
+ }
47
+ resolveOwnerRepo(registry) {
48
+ let namespace = registry.namespace || '';
49
+ let owner = '';
50
+ let repo = '';
51
+ if (namespace.includes('/')) {
52
+ const parts = namespace.split('/');
53
+ owner = parts[0];
54
+ repo = parts[1];
55
+ }
56
+ else if (registry.server && registry.server.includes('/')) {
57
+ try {
58
+ const parsed = GitHubClient.parseRepo(registry.server);
59
+ owner = parsed.owner;
60
+ repo = parsed.repo;
61
+ }
62
+ catch {
63
+ // fall through
64
+ }
65
+ }
66
+ if (!owner || !repo) {
67
+ throw new Error(`GitHub Releases publisher requires repository namespace in "owner/repo" format (got "${registry.namespace || registry.server}").`);
68
+ }
69
+ return { owner, repo };
70
+ }
71
+ async exists(artifact, registry, options) {
72
+ const creds = this.resolveCredentials(registry);
73
+ const token = creds.token || creds.password;
74
+ let owner = '';
75
+ let repo = '';
76
+ try {
77
+ const resolved = this.resolveOwnerRepo(registry);
78
+ owner = resolved.owner;
79
+ repo = resolved.repo;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ const client = new GitHubClient({
85
+ baseUrl: registry.server && registry.server.startsWith('http') ? registry.server : undefined,
86
+ token,
87
+ timeoutMs: options?.timeoutMs
88
+ });
89
+ const version = artifact.tags && artifact.tags.length > 0 ? artifact.tags[0] : 'v1.0.0';
90
+ const tagName = version.startsWith('v') || /^\d/.test(version) ? version : `v${version}`;
91
+ const filename = artifact.source ? path.basename(artifact.source) : artifact.name;
92
+ try {
93
+ const release = await client.getReleaseByTag(owner, repo, tagName);
94
+ if (!release) {
95
+ return false;
96
+ }
97
+ return Boolean(release.assets?.some(a => a.name === filename));
98
+ }
99
+ catch (err) {
100
+ throw new Error(`Failed to check artifact existence in GitHub Releases: ${client.maskSecrets(err?.message || String(err))}`);
101
+ }
102
+ }
103
+ async download(artifact, registry, dest, options) {
104
+ const creds = this.resolveCredentials(registry);
105
+ const { owner, repo } = this.resolveOwnerRepo(registry);
106
+ const client = new GitHubClient({
107
+ baseUrl: registry.server && registry.server.startsWith('http') ? registry.server : undefined,
108
+ token: creds.token || creds.password,
109
+ timeoutMs: options?.timeoutMs
110
+ });
111
+ const version = artifact.tags?.[0] || 'v1.0.0';
112
+ const tagName = version.startsWith('v') || /^\d/.test(version) ? version : `v${version}`;
113
+ const filename = artifact.source ? path.basename(artifact.source) : artifact.name;
114
+ const what = `${artifact.name} ${version} (${filename})`;
115
+ const release = await client.getReleaseByTag(owner, repo, tagName);
116
+ const asset = release?.assets?.find(a => a.name === filename);
117
+ if (!asset) {
118
+ throw new Error(`${what} not found in GitHub release ${owner}/${repo}@${tagName}`);
119
+ }
120
+ // The asset API answers with a redirect to storage when asked for octet-stream
121
+ const assetUrl = client.getRepoApiUrl(owner, repo, `/releases/assets/${asset.id}`);
122
+ this.log(` 📥 Downloading ${what} from GitHub release ${owner}/${repo}@${tagName}`);
123
+ const res = await client.request(assetUrl, { headers: { Accept: 'application/octet-stream' } });
124
+ if (!res.ok) {
125
+ throw await this.downloadError(res, what, assetUrl);
126
+ }
127
+ return this.saveResponse(res, dest, assetUrl);
128
+ }
129
+ async login(registry, _options) {
130
+ const creds = this.resolveCredentials(registry);
131
+ if (!creds.token && !creds.password) {
132
+ this.log(` ℹ No auth token configured for GitHub Releases ${registry.server}`);
133
+ }
134
+ }
135
+ async doPublish(artifact, registry, options) {
136
+ const creds = this.resolveCredentials(registry);
137
+ const token = creds.token || creds.password;
138
+ const { owner, repo } = this.resolveOwnerRepo(registry);
139
+ const client = new GitHubClient({
140
+ baseUrl: registry.server && registry.server.startsWith('http') ? registry.server : undefined,
141
+ token,
142
+ timeoutMs: options?.timeoutMs
143
+ });
144
+ const version = artifact.tags && artifact.tags.length > 0 ? artifact.tags[0] : 'v1.0.0';
145
+ const tagName = version.startsWith('v') || /^\d/.test(version) ? version : `v${version}`;
146
+ let filePath = artifact.source;
147
+ const stat = await fs.stat(filePath).catch(() => null);
148
+ if (!stat || !stat.isFile()) {
149
+ throw new Error(`GitHub Release asset source must be an existing file: ${filePath}`);
150
+ }
151
+ const filename = path.basename(filePath);
152
+ const fileBuffer = await fs.readFile(filePath);
153
+ const digest = `sha256:${crypto.createHash('sha256').update(fileBuffer).digest('hex')}`;
154
+ this.log(` 📤 Uploading release asset "${filename}" to GitHub ${owner}/${repo} release ${tagName}...`);
155
+ if (options?.dryRun) {
156
+ this.log(` [dryRun] Would upload asset ${filename} (${fileBuffer.length} bytes) to GitHub release ${tagName}`);
157
+ return {
158
+ ref: `${owner}/${repo}@${tagName}#${filename}`,
159
+ digest,
160
+ metadata: { owner, repo, tagName, filename, size: fileBuffer.length }
161
+ };
162
+ }
163
+ // Get or create release
164
+ let release = await client.getReleaseByTag(owner, repo, tagName);
165
+ if (!release) {
166
+ this.log(` ✨ Creating new GitHub release ${tagName} in ${owner}/${repo}...`);
167
+ release = await client.createRelease(owner, repo, {
168
+ tagName,
169
+ name: artifact.name || tagName,
170
+ body: `Release ${tagName} published via OmniFlow.`
171
+ });
172
+ }
173
+ const uploaded = await client.uploadReleaseAsset(release.upload_url, filename, fileBuffer);
174
+ return {
175
+ ref: `${owner}/${repo}@${tagName}#${filename}`,
176
+ digest,
177
+ metadata: {
178
+ owner,
179
+ repo,
180
+ tagName,
181
+ filename,
182
+ assetId: uploaded.id,
183
+ downloadUrl: uploaded.browser_download_url,
184
+ releaseUrl: release.html_url,
185
+ size: fileBuffer.length
186
+ }
187
+ };
188
+ }
189
+ }
190
+ // Convenient alias
191
+ export { GitHubReleasePublisher as GitHubGenericPublisher };
192
+ //# sourceMappingURL=GitHubReleasePublisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubReleasePublisher.js","sourceRoot":"","sources":["../../src/artifacts/GitHubReleasePublisher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ export interface GitHubClientConfig {
2
+ baseUrl?: string;
3
+ token?: string;
4
+ timeoutMs?: number;
5
+ }
6
+ export interface ParsedGitHubRepo {
7
+ host: string;
8
+ owner: string;
9
+ repo: string;
10
+ fullName: string;
11
+ }
12
+ export interface GitHubReleaseAsset {
13
+ id: number;
14
+ name: string;
15
+ size?: number;
16
+ browser_download_url?: string;
17
+ }
18
+ export interface GitHubRelease {
19
+ id: number;
20
+ tag_name: string;
21
+ name: string;
22
+ upload_url: string;
23
+ html_url: string;
24
+ assets?: GitHubReleaseAsset[];
25
+ }
26
+ export declare class GitHubClient {
27
+ readonly baseUrl: string;
28
+ readonly token?: string;
29
+ readonly timeoutMs: number;
30
+ constructor(config?: GitHubClientConfig);
31
+ get isGitHubCom(): boolean;
32
+ /**
33
+ * Return sensitive credential strings of length >= 3 for scrubbing.
34
+ */
35
+ getSecrets(): string[];
36
+ maskSecrets(input: string): string;
37
+ extractErrorMessage(response: Response): Promise<string>;
38
+ getAuthHeaders(): Record<string, string>;
39
+ getRepoApiUrl(owner: string, repo: string, subpath?: string): string;
40
+ request(url: string, init?: RequestInit): Promise<Response>;
41
+ /**
42
+ * Get release by tag. Returns null if not found (404).
43
+ */
44
+ getReleaseByTag(owner: string, repo: string, tag: string): Promise<GitHubRelease | null>;
45
+ /**
46
+ * Create a new GitHub Release.
47
+ */
48
+ createRelease(owner: string, repo: string, params: {
49
+ tagName: string;
50
+ name?: string;
51
+ body?: string;
52
+ draft?: boolean;
53
+ prerelease?: boolean;
54
+ }): Promise<GitHubRelease>;
55
+ /**
56
+ * Upload binary asset to a release.
57
+ */
58
+ uploadReleaseAsset(uploadUrlTemplate: string, fileName: string, data: Buffer | Uint8Array, contentType?: string): Promise<{
59
+ id: number;
60
+ name: string;
61
+ browser_download_url: string;
62
+ }>;
63
+ /**
64
+ * Parse GitHub repo URL or slug into host, owner, and repo.
65
+ */
66
+ static parseRepo(urlOrSlug: string, defaultHost?: string): ParsedGitHubRepo;
67
+ /**
68
+ * Determine the API base URL from serverUrl and optional contextPath.
69
+ */
70
+ static resolveApiBase(serverUrl: string, contextPath?: string): string;
71
+ /**
72
+ * Determine whether a hostname is a genuine GitHub host (avoiding suffix/substring spoofing).
73
+ */
74
+ static isGitHubHost(hostname: string): boolean;
75
+ }
76
+ //# sourceMappingURL=GitHubClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubClient.d.ts","sourceRoot":"","sources":["../../src/client/GitHubClient.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAC9B;AAED,qBAAa,YAAY;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;gBAEd,MAAM,GAAE,kBAAuB;IAU3C,IAAI,WAAW,IAAI,OAAO,CAOzB;IAED;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE;IAMtB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI5B,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAI9D,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAWxC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,SAAK,GAAG,MAAM;IAK1D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAcrE;;OAEG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAa9F;;OAEG;IACG,aAAa,CACjB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,UAAU,CAAC,EAAE,OAAO,CAAA;KACrB,GACA,OAAO,CAAC,aAAa,CAAC;IAuBzB;;OAEG;IACG,kBAAkB,CACtB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,WAAW,SAA6B,GACvC,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAA;KAAE,CAAC;IAqBtE;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,SAAe,GAAG,gBAAgB;IA2BjF;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM;IAQtE;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAU/C"}
@@ -0,0 +1,170 @@
1
+ import { maskSecrets, safeFetch, extractErrorMessage } from '@ticatec/omniflow-artifact';
2
+ export class GitHubClient {
3
+ baseUrl;
4
+ token;
5
+ timeoutMs;
6
+ constructor(config = {}) {
7
+ let base = (config.baseUrl || 'https://api.github.com').trim().replace(/\/+$/, '');
8
+ if (!/^https?:\/\//i.test(base)) {
9
+ base = `https://${base}`;
10
+ }
11
+ this.baseUrl = base;
12
+ this.token = config.token;
13
+ this.timeoutMs = config.timeoutMs ?? 30000;
14
+ }
15
+ get isGitHubCom() {
16
+ try {
17
+ const parsed = new URL(this.baseUrl);
18
+ return parsed.hostname === 'github.com' || parsed.hostname === 'api.github.com';
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ /**
25
+ * Return sensitive credential strings of length >= 3 for scrubbing.
26
+ */
27
+ getSecrets() {
28
+ return [this.token].filter((s) => typeof s === 'string' && s.length >= 3);
29
+ }
30
+ maskSecrets(input) {
31
+ return maskSecrets(input, this.getSecrets());
32
+ }
33
+ async extractErrorMessage(response) {
34
+ return extractErrorMessage(response, this.getSecrets());
35
+ }
36
+ getAuthHeaders() {
37
+ const headers = {
38
+ Accept: 'application/vnd.github+json',
39
+ 'X-GitHub-Api-Version': '2022-11-28'
40
+ };
41
+ if (this.token) {
42
+ headers['Authorization'] = `Bearer ${this.token}`;
43
+ }
44
+ return headers;
45
+ }
46
+ getRepoApiUrl(owner, repo, subpath = '') {
47
+ const cleanSubpath = subpath ? (subpath.startsWith('/') ? subpath : `/${subpath}`) : '';
48
+ return `${this.baseUrl}/repos/${owner}/${repo}${cleanSubpath}`;
49
+ }
50
+ async request(url, init = {}) {
51
+ const headers = {
52
+ ...this.getAuthHeaders(),
53
+ ...(init.headers || {})
54
+ };
55
+ return safeFetch(url, {
56
+ ...init,
57
+ headers,
58
+ timeoutMs: this.timeoutMs,
59
+ secrets: this.getSecrets()
60
+ });
61
+ }
62
+ /**
63
+ * Get release by tag. Returns null if not found (404).
64
+ */
65
+ async getReleaseByTag(owner, repo, tag) {
66
+ const url = `${this.getRepoApiUrl(owner, repo)}/releases/tags/${encodeURIComponent(tag)}`;
67
+ const res = await this.request(url);
68
+ if (res.status === 404) {
69
+ return null;
70
+ }
71
+ if (!res.ok) {
72
+ const errText = await this.extractErrorMessage(res);
73
+ throw new Error(`Failed to query GitHub release for tag "${tag}" (${res.status}): ${errText}`);
74
+ }
75
+ return (await res.json());
76
+ }
77
+ /**
78
+ * Create a new GitHub Release.
79
+ */
80
+ async createRelease(owner, repo, params) {
81
+ const url = `${this.getRepoApiUrl(owner, repo)}/releases`;
82
+ const res = await this.request(url, {
83
+ method: 'POST',
84
+ headers: {
85
+ 'Content-Type': 'application/json'
86
+ },
87
+ body: JSON.stringify({
88
+ tag_name: params.tagName,
89
+ name: params.name || params.tagName,
90
+ body: params.body || '',
91
+ draft: params.draft ?? false,
92
+ prerelease: params.prerelease ?? false
93
+ })
94
+ });
95
+ if (!res.ok) {
96
+ const err = await this.extractErrorMessage(res);
97
+ throw new Error(`Failed to create GitHub release "${params.tagName}" (${res.status}): ${err}`);
98
+ }
99
+ return (await res.json());
100
+ }
101
+ /**
102
+ * Upload binary asset to a release.
103
+ */
104
+ async uploadReleaseAsset(uploadUrlTemplate, fileName, data, contentType = 'application/octet-stream') {
105
+ // uploadUrlTemplate is like: https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}
106
+ const cleanUrl = uploadUrlTemplate.replace(/\{.*?\}$/, '');
107
+ const targetUrl = `${cleanUrl}?name=${encodeURIComponent(fileName)}`;
108
+ const res = await this.request(targetUrl, {
109
+ method: 'POST',
110
+ headers: {
111
+ 'Content-Type': contentType,
112
+ 'Content-Length': String(data.byteLength)
113
+ },
114
+ body: data
115
+ });
116
+ if (!res.ok) {
117
+ const err = await this.extractErrorMessage(res);
118
+ throw new Error(`Failed to upload asset "${fileName}" to GitHub release (${res.status}): ${err}`);
119
+ }
120
+ return (await res.json());
121
+ }
122
+ /**
123
+ * Parse GitHub repo URL or slug into host, owner, and repo.
124
+ */
125
+ static parseRepo(urlOrSlug, defaultHost = 'github.com') {
126
+ let clean = urlOrSlug.trim();
127
+ let host = defaultHost;
128
+ if (clean.includes('://')) {
129
+ const parsed = new URL(clean);
130
+ host = parsed.host;
131
+ clean = parsed.pathname;
132
+ }
133
+ else if (clean.includes('@') && clean.includes(':')) {
134
+ const parts = clean.split(':');
135
+ host = parts[0].replace(/.*@/, '');
136
+ clean = parts[1];
137
+ }
138
+ clean = clean.replace(/^\/+/, '').replace(/\.git$/, '');
139
+ const segments = clean.split('/').filter(Boolean);
140
+ if (segments.length < 2) {
141
+ throw new Error(`Invalid GitHub repository path: "${urlOrSlug}". Expected owner/repo format.`);
142
+ }
143
+ const owner = segments[0];
144
+ const repo = segments[1];
145
+ const fullName = `${owner}/${repo}`;
146
+ return { host, owner, repo, fullName };
147
+ }
148
+ /**
149
+ * Determine the API base URL from serverUrl and optional contextPath.
150
+ */
151
+ static resolveApiBase(serverUrl, contextPath) {
152
+ const url = new URL(serverUrl);
153
+ if (url.hostname === 'github.com' || url.hostname === 'www.github.com' || url.hostname === 'api.github.com') {
154
+ return 'https://api.github.com';
155
+ }
156
+ return `${serverUrl.replace(/\/+$/, '')}${contextPath || ''}/api/v3`;
157
+ }
158
+ /**
159
+ * Determine whether a hostname is a genuine GitHub host (avoiding suffix/substring spoofing).
160
+ */
161
+ static isGitHubHost(hostname) {
162
+ const host = hostname.toLowerCase().trim();
163
+ return (host === 'github.com' ||
164
+ host.endsWith('.github.com') ||
165
+ host === 'api.github.com' ||
166
+ host === 'ghcr.io' ||
167
+ host.endsWith('.ghcr.io'));
168
+ }
169
+ }
170
+ //# sourceMappingURL=GitHubClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubClient.js","sourceRoot":"","sources":["../../src/client/GitHubClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { PluginContext } from '@ticatec/omniflow-core';
2
+ import type { ArtifactPublisherRegistry } from '@ticatec/omniflow-artifact';
3
+ import { GitHubContainerPublisher } from './artifacts/GitHubContainerPublisher.js';
4
+ import { GitHubNpmPublisher } from './artifacts/GitHubNpmPublisher.js';
5
+ import { GitHubMavenPublisher } from './artifacts/GitHubMavenPublisher.js';
6
+ import { GitHubReleasePublisher } from './artifacts/GitHubReleasePublisher.js';
7
+ export * from './client/GitHubClient.js';
8
+ export * from './artifacts/GitHubContainerPublisher.js';
9
+ export * from './artifacts/GitHubNpmPublisher.js';
10
+ export * from './artifacts/GitHubMavenPublisher.js';
11
+ export * from './artifacts/GitHubReleasePublisher.js';
12
+ export interface RegisterGitHubOptions {
13
+ artifactRegistry?: ArtifactPublisherRegistry;
14
+ }
15
+ /**
16
+ * Standard OmniFlow Plugin SPI entry point.
17
+ */
18
+ export declare function register(ctx: PluginContext): void;
19
+ export default register;
20
+ /**
21
+ * Register all GitHub artifact publishers into the artifact registry.
22
+ */
23
+ export declare function registerGitHub(options?: RegisterGitHubOptions): {
24
+ containerPublisher: GitHubContainerPublisher;
25
+ npmPublisher: GitHubNpmPublisher;
26
+ mavenPublisher: GitHubMavenPublisher;
27
+ releasePublisher: GitHubReleasePublisher;
28
+ };
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAA;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAA;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAE9E,cAAc,0BAA0B,CAAA;AACxC,cAAc,yCAAyC,CAAA;AACvD,cAAc,mCAAmC,CAAA;AACjD,cAAc,qCAAqC,CAAA;AACnD,cAAc,uCAAuC,CAAA;AAErD,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,yBAAyB,CAAA;CAC7C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAEjD;AAED,eAAe,QAAQ,CAAA;AAEvB;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG;IACnE,kBAAkB,EAAE,wBAAwB,CAAA;IAC5C,YAAY,EAAE,kBAAkB,CAAA;IAChC,cAAc,EAAE,oBAAoB,CAAA;IACpC,gBAAgB,EAAE,sBAAsB,CAAA;CACzC,CAmBA"}
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ import { GitHubContainerPublisher } from './artifacts/GitHubContainerPublisher.js';
2
+ import { GitHubNpmPublisher } from './artifacts/GitHubNpmPublisher.js';
3
+ import { GitHubMavenPublisher } from './artifacts/GitHubMavenPublisher.js';
4
+ import { GitHubReleasePublisher } from './artifacts/GitHubReleasePublisher.js';
5
+ export * from './client/GitHubClient.js';
6
+ export * from './artifacts/GitHubContainerPublisher.js';
7
+ export * from './artifacts/GitHubNpmPublisher.js';
8
+ export * from './artifacts/GitHubMavenPublisher.js';
9
+ export * from './artifacts/GitHubReleasePublisher.js';
10
+ /**
11
+ * Standard OmniFlow Plugin SPI entry point.
12
+ */
13
+ export function register(ctx) {
14
+ registerGitHub({ artifactRegistry: ctx.artifactRegistry });
15
+ }
16
+ export default register;
17
+ /**
18
+ * Register all GitHub artifact publishers into the artifact registry.
19
+ */
20
+ export function registerGitHub(options = {}) {
21
+ const containerPublisher = new GitHubContainerPublisher();
22
+ const npmPublisher = new GitHubNpmPublisher();
23
+ const mavenPublisher = new GitHubMavenPublisher();
24
+ const releasePublisher = new GitHubReleasePublisher();
25
+ if (options.artifactRegistry) {
26
+ options.artifactRegistry.register(containerPublisher);
27
+ options.artifactRegistry.register(npmPublisher);
28
+ options.artifactRegistry.register(mavenPublisher);
29
+ options.artifactRegistry.register(releasePublisher);
30
+ }
31
+ return {
32
+ containerPublisher,
33
+ npmPublisher,
34
+ mavenPublisher,
35
+ releasePublisher
36
+ };
37
+ }
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAA;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAA;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAE9E,cAAc,0BAA0B,CAAA;AACxC,cAAc,yCAAyC,CAAA;AACvD,cAAc,mCAAmC,CAAA;AACjD,cAAc,qCAAqC,CAAA;AACnD,cAAc,uCAAuC,CAAA;AAMrD;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAkB;IACzC,cAAc,CAAC,EAAE,gBAAgB,EAAE,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAA;AAC5D,CAAC;AAED,eAAe,QAAQ,CAAA;AAEvB;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,UAAiC,EAAE;IAMhE,MAAM,kBAAkB,GAAG,IAAI,wBAAwB,EAAE,CAAA;IACzD,MAAM,YAAY,GAAG,IAAI,kBAAkB,EAAE,CAAA;IAC7C,MAAM,cAAc,GAAG,IAAI,oBAAoB,EAAE,CAAA;IACjD,MAAM,gBAAgB,GAAG,IAAI,sBAAsB,EAAE,CAAA;IAErD,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;QACrD,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;QAC/C,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA;QACjD,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAA;IACrD,CAAC;IAED,OAAO;QACL,kBAAkB;QAClB,YAAY;QACZ,cAAc;QACd,gBAAgB;KACjB,CAAA;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@ticatec/omniflow-github",
3
+ "version": "1.0.0",
4
+ "description": "All-in-one GitHub artifact provider for OmniFlow: GitHub Container Registry (ghcr.io), NPM, Maven, and Releases generic packages",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "license": "MIT",
15
+ "dependencies": {
16
+ "@ticatec/omniflow-artifact": "^1.0.0",
17
+ "@ticatec/omniflow-core": "^1.0.0"
18
+ },
19
+ "devDependencies": {
20
+ "@jest/globals": "^30.4.1",
21
+ "@types/jest": "^30.0.0",
22
+ "@types/node": "^22.10.2",
23
+ "jest": "^30.4.2",
24
+ "ts-jest": "^29.4.9",
25
+ "typescript": "^5.7.2"
26
+ },
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "src",
33
+ "README.md",
34
+ "README_CN.md",
35
+ "LICENSE"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc",
42
+ "clean": "rm -rf dist",
43
+ "prebuild": "npm run clean",
44
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest",
45
+ "typecheck": "tsc --noEmit",
46
+ "publish:npm": "pnpm publish --access public --no-git-checks"
47
+ }
48
+ }
@@ -0,0 +1,54 @@
1
+ import { BaseDockerPublisher } from '@ticatec/omniflow-artifact'
2
+ import type { RegistryConfig } from '@ticatec/omniflow-artifact'
3
+ import { GitHubClient } from '../client/GitHubClient.js'
4
+
5
+ /**
6
+ * GitHub Container Registry (GHCR) Publisher.
7
+ *
8
+ * Supports ghcr.io and GitHub Enterprise Container Registries.
9
+ */
10
+ export class GitHubContainerPublisher extends BaseDockerPublisher {
11
+ readonly id = 'github-container'
12
+ readonly name = 'GitHub Container Registry'
13
+ readonly platform = 'github'
14
+ override readonly priority = 20
15
+
16
+ override detect(registry: RegistryConfig): boolean {
17
+ if (registry.type !== 'docker' && registry.type !== 'container') {
18
+ return false
19
+ }
20
+
21
+ const regName = (registry.name || '').toLowerCase()
22
+ if (regName === 'github' || regName === 'ghcr' || regName.startsWith('github-') || regName.startsWith('ghcr-')) {
23
+ return true
24
+ }
25
+
26
+ const server = (registry.server || '').toLowerCase()
27
+ try {
28
+ const parsed = new URL(server.includes('://') ? server : `https://${server}`)
29
+ const host = parsed.hostname.toLowerCase()
30
+ return host === 'ghcr.io' || host.endsWith('.ghcr.io') || GitHubClient.isGitHubHost(host)
31
+ } catch {
32
+ return false
33
+ }
34
+ }
35
+
36
+ override buildRepositoryUrl(registry: RegistryConfig, imageName: string): string {
37
+ let host = this.normalizeServerHost(registry.server)
38
+ if (!host || host === 'github' || host === 'ghcr') {
39
+ host = 'ghcr.io'
40
+ }
41
+
42
+ const cleanImage = imageName.replace(/^\/+/, '')
43
+ const ns = (registry.namespace || '').replace(/\/+$/, '')
44
+
45
+ if (ns) {
46
+ if (cleanImage.startsWith(`${ns}/`)) {
47
+ return `${host}/${cleanImage}`
48
+ }
49
+ return `${host}/${ns}/${cleanImage}`
50
+ }
51
+
52
+ return `${host}/${cleanImage}`
53
+ }
54
+ }