Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions src/targets/__tests__/docker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ describe('DockerTarget', () => {
delete process.env.DOCKER_GCR_IO_PASSWORD;
delete process.env.GITHUB_ACTOR;
delete process.env.GITHUB_TOKEN;
delete process.env.GITHUB_API_TOKEN;
});

afterAll(() => {
Expand Down Expand Up @@ -465,6 +466,73 @@ describe('DockerTarget', () => {
expect(target.dockerConfig.target.credentials!.password).toBe('github-token');
});

it('falls back to GITHUB_API_TOKEN for ghcr.io when GITHUB_TOKEN is not set', () => {
process.env.GITHUB_ACTOR = 'github-actor';
process.env.GITHUB_API_TOKEN = 'github-api-token';

const target = new DockerTarget(
{
name: 'docker',
source: 'ghcr.io/org/image',
target: 'ghcr.io/org/image',
},
new NoneArtifactProvider()
);

expect(target.dockerConfig.target.credentials!.username).toBe('github-actor');
expect(target.dockerConfig.target.credentials!.password).toBe('github-api-token');
});

it('falls back to x-access-token username for ghcr.io when GITHUB_ACTOR is not set', () => {
process.env.GITHUB_TOKEN = 'github-token';

const target = new DockerTarget(
{
name: 'docker',
source: 'ghcr.io/org/image',
target: 'ghcr.io/org/image',
},
new NoneArtifactProvider()
);

expect(target.dockerConfig.target.credentials!.username).toBe('x-access-token');
expect(target.dockerConfig.target.credentials!.password).toBe('github-token');
});

it('falls back to x-access-token username for ghcr.io when GITHUB_ACTOR is empty', () => {
process.env.GITHUB_ACTOR = '';
process.env.GITHUB_TOKEN = 'github-token';

const target = new DockerTarget(
{
name: 'docker',
source: 'ghcr.io/org/image',
target: 'ghcr.io/org/image',
},
new NoneArtifactProvider()
);

expect(target.dockerConfig.target.credentials!.username).toBe('x-access-token');
expect(target.dockerConfig.target.credentials!.password).toBe('github-token');
});

it('uses x-access-token and GITHUB_API_TOKEN for ghcr.io (app token scenario)', () => {
// This simulates the getsentry/publish workflow with release bot token
process.env.GITHUB_API_TOKEN = 'release-bot-token';

const target = new DockerTarget(
{
name: 'docker',
source: 'ghcr.io/org/image',
target: 'ghcr.io/org/image',
},
new NoneArtifactProvider()
);

expect(target.dockerConfig.target.credentials!.username).toBe('x-access-token');
expect(target.dockerConfig.target.credentials!.password).toBe('release-bot-token');
});

it('uses default DOCKER_* env vars for Docker Hub', () => {
process.env.DOCKER_USERNAME = 'dockerhub-user';
process.env.DOCKER_PASSWORD = 'dockerhub-pass';
Expand Down Expand Up @@ -536,6 +604,25 @@ describe('DockerTarget', () => {
expect(target.dockerConfig.target.credentials!.password).toBe('default-pass');
});

it('falls back to DOCKER_* when registry-specific vars are empty strings', () => {
process.env.DOCKER_GCR_IO_USERNAME = '';
process.env.DOCKER_GCR_IO_PASSWORD = '';
process.env.DOCKER_USERNAME = 'default-user';
process.env.DOCKER_PASSWORD = 'default-pass';

const target = new DockerTarget(
{
name: 'docker',
source: 'ghcr.io/org/image',
target: 'gcr.io/project/image',
},
new NoneArtifactProvider()
);

expect(target.dockerConfig.target.credentials!.username).toBe('default-user');
expect(target.dockerConfig.target.credentials!.password).toBe('default-pass');
});

it('throws when no credentials are available', () => {
expect(
() =>
Expand Down
11 changes: 7 additions & 4 deletions src/targets/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,18 @@ export class DockerTarget extends BaseTarget {
// GHCR defaults: use GitHub Actions built-in env vars
// GITHUB_ACTOR and GITHUB_TOKEN are available by default in GitHub Actions
// See: https://docs.github.com/en/actions/reference/workflows-and-actions/variables
username = username ?? process.env.GITHUB_ACTOR;
password = password ?? process.env.GITHUB_TOKEN;
// GITHUB_API_TOKEN is used by getsentry/publish workflow with release bot token
// x-access-token works with GitHub App installation tokens and PATs
username = username || process.env.GITHUB_ACTOR || 'x-access-token';
password = password || process.env.GITHUB_TOKEN || process.env.GITHUB_API_TOKEN;
}
}

// 3. Fallback to defaults (only for target registry, not for source)
// Use || to treat empty strings as "not set" (consistent with ghcr.io logic above)
if (useDefaultFallback) {
username = username ?? process.env.DOCKER_USERNAME;
password = password ?? process.env.DOCKER_PASSWORD;
username = username || process.env.DOCKER_USERNAME;
password = password || process.env.DOCKER_PASSWORD;
}
}

Expand Down
Loading