Fix Kaniko registry auth and push target for Harbor builds.

Mount docker config as config.json (Kaniko requirement), push via
harbor-registry internal URL, and wire harbor_registry_user credentials
in Helm/GitOps values.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-07-10 12:29:23 +03:30
parent 214b617be0
commit 54ab2f2f05
5 changed files with 57 additions and 12 deletions
@@ -125,6 +125,15 @@ spec:
name: {{ include "cloudhost-platform.secretName" . }}
key: mizbansms-password
{{- end }}
{{- if .Values.registry.credentialsSecret }}
- name: REGISTRY_USERNAME
value: {{ .Values.registry.username | default "harbor_registry_user" | quote }}
- name: REGISTRY_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.registry.credentialsSecret | quote }}
key: {{ .Values.registry.credentialsPasswordKey | default "REGISTRY_CREDENTIAL_PASSWORD" | quote }}
{{- end }}
{{- include "cloudhost-platform.buildEnv" . | nindent 12 }}
{{- range $key, $val := .Values.backend.env }}
- name: {{ $key }}
@@ -28,6 +28,12 @@ images:
tag: "1.0.0"
pullPolicy: IfNotPresent
# Kaniko push credentials — harbor_registry_user for harbor-registry:5000 (Harbor production).
registry:
credentialsSecret: ""
credentialsPasswordKey: REGISTRY_CREDENTIAL_PASSWORD
username: harbor_registry_user
# Kaniko job images — defaults pull from Harbor proxy-cache.
# Override any line for a different registry/tag.
build:
+7 -4
View File
@@ -434,10 +434,10 @@ export class BuildService {
* Returns { imageUri, buildLog } — the full image URI and the build logs.
*/
async buildImage(app: Application, deploymentId?: string): Promise<{ imageUri: string; buildLog: string }> {
const registryUrl = this.registryService.getRegistryUrl();
const registryPushUrl = this.registryService.getRegistryPushUrl();
const buildNamespace = this.registryService.getBuildNamespace();
const tag = `${Date.now()}`;
const imageUri = this.registryService.buildImageReference(app.userId, app.name, tag);
const imageUri = this.registryService.buildPushImageReference(app.userId, app.name, tag);
this.logger.log(`Starting image build for ${app.name}${imageUri}`);
@@ -534,7 +534,7 @@ export class BuildService {
'--context=dir:///workspace/source',
`--destination=${imageUri}`,
'--cache=true',
`--cache-repo=${registryUrl}/${app.userId}/cache`,
`--cache-repo=${registryPushUrl}/${app.userId}/cache`,
'--insecure',
'--skip-tls-verify',
'--single-snapshot',
@@ -544,7 +544,10 @@ export class BuildService {
const volumes: any[] = [
{
name: 'docker-config',
secret: { secretName: 'registry-credentials' },
secret: {
secretName: 'registry-credentials',
items: [{ key: '.dockerconfigjson', path: 'config.json' }],
},
},
{
name: 'dockerfile',
+30 -8
View File
@@ -35,13 +35,20 @@ export class RegistryService {
return slash === -1 ? url : url.slice(0, slash);
}
/** Push target host:port (may differ from pull URL on Harbor setups). */
getRegistryPushHost(): string {
/** Push target host[:port][/project] — Kaniko destination (may differ from pull URL on Harbor). */
getRegistryPushUrl(): string {
const buildNs = this.getBuildNamespace();
const url = this.configService.get<string>('registry.url') || `registry.${buildNs}.svc.cluster.local:5000`;
const normalized = url.replace(/^https?:\/\//, '');
const slash = normalized.indexOf('/');
return slash === -1 ? normalized : normalized.slice(0, slash);
const url =
this.configService.get<string>('registry.url') ||
`registry.${buildNs}.svc.cluster.local:5000`;
return url.replace(/^https?:\/\//, '');
}
/** Push target host:port only, no repository path prefix. */
getRegistryPushHost(): string {
const url = this.getRegistryPushUrl();
const slash = url.indexOf('/');
return slash === -1 ? url : url.slice(0, slash);
}
getRegistryCredentials(): { username: string; password: string } {
@@ -55,6 +62,11 @@ export class RegistryService {
return `${this.getRegistryUrl()}/${userId}/${appName}:${tag}`;
}
/** Kaniko push target — uses registry.url (in-cluster harbor-registry on Harbor setups). */
buildPushImageReference(userId: string, appName: string, tag: string): string {
return `${this.getRegistryPushUrl()}/${userId}/${appName}:${tag}`;
}
parseImageReference(imageRef: string): ParsedImageReference {
const normalized = imageRef.replace(/^https?:\/\//, '');
const slashIdx = normalized.indexOf('/');
@@ -72,10 +84,20 @@ export class RegistryService {
};
}
/** Re-point any stored image (e.g. legacy external host) to the in-cluster registry. */
/** Re-point any stored image (e.g. push host) to the pull registry URL for kubelet. */
normalizeImageReference(imageRef: string): string {
const { repository, tag } = this.parseImageReference(imageRef);
return `${this.getRegistryUrl()}/${repository}:${tag}`;
const pullBase = this.getRegistryUrl().replace(/\/$/, '');
const slash = pullBase.indexOf('/');
const pullPath = slash === -1 ? '' : pullBase.slice(slash + 1);
let repo = repository;
if (pullPath && (repo === pullPath || repo.startsWith(`${pullPath}/`))) {
repo = repo === pullPath ? '' : repo.slice(pullPath.length + 1);
}
if (!repo) {
throw new Error(`Invalid image reference after normalization: ${imageRef}`);
}
return `${pullBase}/${repo}:${tag}`;
}
buildDockerConfigJson(): string {
@@ -11,6 +11,11 @@
namespace: cloudhost
createNamespace: false
registry:
credentialsSecret: harbor-core
credentialsPasswordKey: REGISTRY_CREDENTIAL_PASSWORD
username: harbor_registry_user
global:
storageClass: local-path