gitea

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package gitea 는 Gitea REST API 로 리포지토리를 프로비저닝한다.

GitHub 어댑터와 형태가 비슷하지만 세 가지가 다르다.

하나, 조직을 만들 수 있다. GitHub Organization 은 API 로 생성되지 않아 EnsureGroup 이 "확인"만 하지만, Gitea 는 실제로 만든다 — 스택 안에 설치되는 Git 서버라 우리가 소유자다.

둘, 파일 커밋에 Git Data API 대신 배치 contents API 를 쓴다. Gitea 는 POST /repos/{owner}/{repo}/contents 하나로 여러 파일을 한 커밋에 담을 수 있다. 스캐폴딩이 여러 커밋으로 쪼개지면 Argo CD 가 중간 상태를 동기화한다.

셋, 클러스터 안에 있다. 주소가 서비스 DNS 라 외부 노출이 필요 없다.

Index

Constants

View Source
const (
	// ESOSecretStoreName 은 스택 네임스페이스에 있는 SecretStore 이름이다.
	//
	// 스택 모듈이 만든다(helm/external-secrets.go). 모듈 간 직접 import 가
	// 금지돼 값을 각자 들고 있으므로, 갈라지면 ESO 가 Secret 을 만들지 못하고
	// agent 파드는 FailedMount 로 멈춘다.
	ESOSecretStoreName = "nullus-openbao"

	// CISecretPrefix 는 파이프라인 자격증명 Secret 이름의 접두사다.
	//
	// Argo CD 리포 Secret 의 기존 규약(nullus-repo-<app>)과 짝을 맞춘다.
	// 파이프라인 단위라 한 자격증명의 유출이 다른 파이프라인으로 번지지 않고,
	// 파이프라인을 지울 때 함께 지울 수 있다.
	CISecretPrefix = "nullus-ci-"
)
View Source
const (
	// SecretProvider 는 토큰을 보관할 시크릿 백엔드다.
	SecretProvider = "openbao"

	// AutomationTokenName 은 Nullus 가 발급하는 액세스 토큰의 이름이다.
	// 사람이 만든 토큰과 구분되어야 재발급 시 정리 대상을 특정할 수 있다.
	AutomationTokenName = "nullus-automation"

	// AutomationUser 는 차트가 만드는 관리자 계정이다.
	// 스택 설치의 provisioning_secrets 가 같은 이름으로 자격증명을 만든다
	// (internal/stack/domain.GiteaAdminUser). 갈라지면 인증이 실패한다.
	AutomationUser = "gitea_admin"
)
View Source
const (
	// APIPathPrefix 는 Gitea REST API 의 경로 접두사다.
	APIPathPrefix = "/api/v1"
)

Variables

This section is empty.

Functions

func AdminPasswordPath

func AdminPasswordPath(env, orgID string) string

AdminPasswordPath 는 Gitea 관리자 비밀번호의 시크릿 경로다.

스택 설치의 provisioning_secrets 가 쓰는 경로와 같아야 한다 (helm/secret-provisioning.go 의 "artifacts/gitea/admin-password"). 토큰 폐기에 관리자 자격이 필요하다 — CLI 에 삭제 명령이 없어 API 를 쓴다.

func CISecretName

func CISecretName(app string) string

CISecretName 은 앱의 파이프라인 자격증명 Secret 이름이다.

스캐폴딩이 만든 Jenkinsfile 의 envFrom.secretRef 가 같은 이름을 가리킨다 (scaffold 의 ciSecretName). 갈라지면 agent 파드가 없는 Secret 을 참조해 기동하지 못한다.

func TokenSecretPath

func TokenSecretPath(env, orgID string) string

TokenSecretPath 는 액세스 토큰의 시크릿 경로다.

스택 모듈의 규약(kv/nullus/{env}/{org}/{module}/{provider}/...)을 따른다.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client 는 port.SCMProvisioner 의 Gitea 구현체다.

func NewClient

func NewClient(baseURL, token string) *Client

NewClient 는 Gitea REST 클라이언트를 만든다.

baseURL 은 API 접두사를 뺀 서버 주소다 (예: http://gitea-http.nullus.svc:3000). token 은 Gitea 액세스 토큰이다.

func (*Client) BaseURL

func (c *Client) BaseURL() string

BaseURL 은 이 클라이언트가 바라보는 서버 주소다.

func (*Client) CommitFiles

func (c *Client) CommitFiles(ctx context.Context, projectID string, spec port.CommitSpec) error

CommitFiles 는 여러 파일을 한 커밋으로 올린다(upsert).

커밋이 여러 개로 쪼개지면 Argo CD 가 중간 상태를 동기화한다 — 매니페스트만 있고 이미지가 아직 없는 커밋을 배포하려다 실패한다. Gitea 의 배치 contents API 로 한 번에 밀어 넣는다.

파일마다 create / update 를 나눠야 한다. Gitea 는 기존 파일을 update 로 보내면서 그 파일의 sha 를 함께 요구한다 — create 로 보내면 409 가 난다.

func (*Client) DeleteProject

func (c *Client) DeleteProject(ctx context.Context, projectID string) error

DeleteProject 는 리포지토리를 지운다.

이미 없으면 성공으로 본다 — 삭제의 목표는 "없는 상태" 이고, 404 를 오류로 올리면 앞선 시도가 절반쯤 성공한 뒤 재시도할 때 영영 끝나지 않는다.

func (*Client) EnsureGroup

func (c *Client) EnsureGroup(ctx context.Context, spec port.GroupSpec) (*port.SCMGroup, error)

EnsureGroup 은 조직을 조회하고 없으면 만든다.

GitHub 과 달리 Gitea 는 조직을 API 로 만들 수 있다 — 스택 안에 설치되는 Git 서버라 우리가 소유자다.

func (*Client) EnsureOrgMember

func (c *Client) EnsureOrgMember(ctx context.Context, org, email string) error

EnsureOrgMember 는 이메일로 찾은 사용자를 조직의 write 팀에 넣는다.

플랫폼이 만든 저장소는 자동화 계정(gitea_admin) 소유의 private 조직 안에 있다. SSO 로 들어온 사람은 그 조직의 멤버가 아니라, 로그인은 되는데 화면이 텅 비어 보인다 — 그런데 개발자는 그 저장소에 앱 소스를 밀어야 한다.

멱등하다. 이미 멤버면 Gitea 가 성공으로 답한다.

func (*Client) EnsureProject

func (c *Client) EnsureProject(ctx context.Context, spec port.ProjectSpec) (*port.SCMProject, error)

EnsureProject 는 리포지토리를 조회하고 없으면 만든다.

func (*Client) EnsureWebhook

func (c *Client) EnsureWebhook(ctx context.Context, projectID, targetURL, secret string) error

EnsureWebhook 은 리포지토리에 webhook 을 걸어 둔다(멱등).

Jenkins multibranch job 은 스스로 폴링하지 않는 한 새 커밋을 모른다. 폴링은 지연이 크고 리포가 늘수록 부하가 커지므로 push webhook 을 건다.

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping 은 현재 토큰이 실제로 인증되는지 확인한다.

보관된 토큰은 폐기·만료될 수 있다. 쓰기 전에 확인하지 않으면 이후 모든 호출이 401 로 죽고 원인이 프로비저닝 실패처럼 보인다.

func (*Client) WithHTTPClient

func (c *Client) WithHTTPClient(h *http.Client) *Client

WithHTTPClient 는 타임아웃·전송 계층을 교체한다.

type CredentialPlane

type CredentialPlane struct {
	// contains filtered or unexported fields
}

CredentialPlane 은 파이프라인 자격증명을 OpenBao → ESO → K8s Secret 으로 나른다.

Gitea 에는 GitLab 같은 프로젝트 CI 변수 저장소가 없다. Jenkins Credentials 를 1차 저장소로 쓰지 않는 이유는 자격증명 사본이 하나 더 생기고 회전 경로가 둘로 갈리기 때문이다 — OpenBao 가 단일 출처라는 원칙이 깨진다.

매니페스트를 적용하지 않고 렌더링만 한다. 클러스터 접근은 유스케이스가 한곳에서 맡는다(Argo CD 리소스와 같은 경로로 적용된다).

func NewCredentialPlane

func NewCredentialPlane(secrets SecretWriter, env, orgID, stackID, namespace string) *CredentialPlane

NewCredentialPlane 은 CredentialPlane 을 만든다.

func (*CredentialPlane) Provision

func (p *CredentialPlane) Provision(
	ctx context.Context,
	app string,
	vars []port.PipelineVariable,
) (string, error)

Provision 은 값들을 OpenBao 에 쓰고 그것을 참조하는 ExternalSecret 을 만든다.

변수를 한 번에 다 받는다 — ExternalSecret 은 항목 전체를 한 문서로 선언하므로 변수마다 따로 적용하면 마지막 것만 남는다.

type KubectlRunner

type KubectlRunner func(ctx context.Context, kubeconfig []byte, args ...string) ([]byte, error)

KubectlRunner 는 kubectl 실행을 추상화한다.

다른 모듈의 동일 타입을 재사용하지 않는다 — 모듈 간 직접 import 를 피하기 위해 CI/CD 컨텍스트가 자기 계약을 소유한다.

type SecretStore

type SecretStore interface {
	GetTokenForStack(ctx context.Context, provider, stackID, path string) (string, error)
	PutTokenForStack(ctx context.Context, provider, stackID, path, value string) error
}

SecretStore 는 토큰 보관에 필요한 최소 동작만 노출한다.

스택 범위 접근을 쓴다 — OpenBao 는 스택마다 배포되므로 전역 주소가 하나일 수 없고, 해당 스택의 저장소에 넣어야 ESO 와 같은 곳을 본다.

type SecretWriter

type SecretWriter interface {
	PutTokenForStack(ctx context.Context, provider, stackID, path, value string) error
}

SecretWriter 는 OpenBao 기록에 필요한 최소 동작만 노출한다.

type TokenIssuer

type TokenIssuer struct {
	// contains filtered or unexported fields
}

TokenIssuer 는 Gitea 액세스 토큰을 확보한다.

Gitea 를 외부에 노출하지 않고도 동작해야 하므로 API 가 아니라 파드 안의 gitea CLI 로 발급한다 — GitLab 이 toolbox 의 rails 콘솔을 쓰는 것과 같은 이유다. 토큰 값은 발급 시점에만 읽을 수 있어 즉시 시크릿 저장소에 보관한다.

func NewTokenIssuer

func NewTokenIssuer(kubeconfig port.KubeconfigProvider, runKubectl KubectlRunner, secrets SecretStore) *TokenIssuer

NewTokenIssuer 는 TokenIssuer 를 만든다.

func (*TokenIssuer) EnsureToken

func (t *TokenIssuer) EnsureToken(ctx context.Context, spec port.SCMTokenSpec) (string, error)

EnsureToken 은 보관된 토큰을 돌려주고, 없거나 Force 면 새로 발급한다.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL