Skip to content
85 changes: 0 additions & 85 deletions src/credentials/__tests__/app-token.integration.test.ts

This file was deleted.

106 changes: 0 additions & 106 deletions src/credentials/__tests__/app-token.test.ts

This file was deleted.

75 changes: 75 additions & 0 deletions src/credentials/__tests__/github-app.integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { execSync } from 'node:child_process';
import { afterAll, describe, expect, it } from 'vitest';
import { fetchGitHubAppCredentials } from '../github-app.js';

const OP_REFS = {
pat: 'op://Team AI Agent/Docker Agent GHA Machine user/PAT',
orgMembershipToken: 'op://Team AI Agent/Docker Agent GitHub Action/GH org membership token',
};

// CI: env vars already exported by the setup-credentials step
const envCredentials =
process.env.GITHUB_APP_TOKEN && process.env.ORG_MEMBERSHIP_TOKEN
? { pat: process.env.GITHUB_APP_TOKEN, orgMembershipToken: process.env.ORG_MEMBERSHIP_TOKEN }
: undefined;

// Local dev: read from 1Password
function getOpCredentials() {
try {
const pat = execSync(`op read "${OP_REFS.pat}"`, { encoding: 'utf8' }).trim();
const orgMembershipToken = execSync(`op read "${OP_REFS.orgMembershipToken}"`, {
encoding: 'utf8',
}).trim();
if (pat && orgMembershipToken) return { pat, orgMembershipToken };
} catch {
// op not available or not signed in
}
return undefined;
}
// Don't call op if CI already has values
const opCredentials = envCredentials ? undefined : getOpCredentials();

const hasAnyCredentials = Boolean(envCredentials ?? opCredentials);

afterAll(() => {
delete process.env.GITHUB_APP_TOKEN;
delete process.env.ORG_MEMBERSHIP_TOKEN;
});

// Scenario 1: no credentials at all — verify fetchGitHubAppCredentials throws
describe.skipIf(hasAnyCredentials)(
'fetchGitHubAppCredentials (integration — AWS unavailable)',
() => {
it('throws when AWS credentials are unavailable', async () => {
await expect(fetchGitHubAppCredentials()).rejects.toThrow('AWS Secrets Manager call failed');
});
},
);

// Scenario 2: CI path — env vars already set by setup-credentials, just assert they're present
describe.skipIf(!envCredentials)('fetchGitHubAppCredentials (integration — CI)', () => {
it('exports GITHUB_APP_TOKEN and ORG_MEMBERSHIP_TOKEN', () => {
expect(process.env.GITHUB_APP_TOKEN).toBeTruthy();
expect(process.env.ORG_MEMBERSHIP_TOKEN).toBeTruthy();
});
});

// Scenario 3: local dev path — validate PAT via GitHub API (no AWS needed)
describe.skipIf(!opCredentials)('fetchGitHubAppCredentials (integration — local dev)', () => {
// opCredentials is guaranteed non-null inside this describe block
const creds = opCredentials ?? { pat: '', orgMembershipToken: '' };

it('PAT resolves to a valid GitHub user', () => {
const login = execSync(`GH_TOKEN="${creds.pat}" gh api /user --jq '.login'`, {
encoding: 'utf8',
}).trim();
expect(login).toBeTruthy();
}, 10_000);

it('org membership token resolves to a valid GitHub user', () => {
const login = execSync(`GH_TOKEN="${creds.orgMembershipToken}" gh api /user --jq '.login'`, {
encoding: 'utf8',
}).trim();
expect(login).toBeTruthy();
}, 10_000);
});
23 changes: 8 additions & 15 deletions src/credentials/__tests__/github-app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ vi.mock('@aws-sdk/client-secrets-manager', () => ({
}));

const VALID_SECRET = JSON.stringify({
app_id: 'test-app-id',
private_key: 'FAKE_PRIVATE_KEY_FOR_TESTING',
pat: 'test-pat-token',
org_membership_token: 'test-org-token',
});

Expand All @@ -32,28 +31,22 @@ describe('fetchGitHubAppCredentials', () => {
it('sets env vars and masks fields on valid secret', async () => {
mockSend.mockResolvedValue({ SecretString: VALID_SECRET });
await fetchGitHubAppCredentials();
expect(core.exportVariable).toHaveBeenCalledWith('GITHUB_APP_ID', 'test-app-id');
expect(core.exportVariable).toHaveBeenCalledWith('GITHUB_APP_TOKEN', 'test-pat-token');
expect(core.exportVariable).toHaveBeenCalledWith('ORG_MEMBERSHIP_TOKEN', 'test-org-token');
expect(core.exportVariable).toHaveBeenCalledWith(
'GITHUB_APP_PRIVATE_KEY',
'FAKE_PRIVATE_KEY_FOR_TESTING',
);
expect(core.setSecret).toHaveBeenCalledWith(
expect.stringContaining('FAKE_PRIVATE_KEY_FOR_TESTING'),
);
expect(core.setSecret).toHaveBeenCalledWith(expect.stringContaining('test-pat-token'));
});

it('exits with error when app_id is missing', async () => {
it('exits with error when pat is missing', async () => {
mockSend.mockResolvedValue({
SecretString: JSON.stringify({ app_id: '', private_key: 'key', org_membership_token: 'tok' }),
SecretString: JSON.stringify({ pat: '', org_membership_token: 'test-org-token' }),
});
await fetchGitHubAppCredentials();
expect(process.exit).toHaveBeenCalledWith(1);
});

it('exits with error when private_key is missing', async () => {
it('exits with error when org_membership_token is missing', async () => {
mockSend.mockResolvedValue({
SecretString: JSON.stringify({ app_id: 'id', private_key: '', org_membership_token: 'tok' }),
SecretString: JSON.stringify({ pat: 'test-pat-token', org_membership_token: '' }),
});
await fetchGitHubAppCredentials();
expect(process.exit).toHaveBeenCalledWith(1);
Expand All @@ -77,6 +70,6 @@ describe('fetchGitHubAppCredentials', () => {
mockSend.mockResolvedValue({ SecretString: VALID_SECRET });
const fakeCredentials = vi.fn();
await fetchGitHubAppCredentials(fakeCredentials as never);
expect(core.exportVariable).toHaveBeenCalledWith('GITHUB_APP_ID', 'test-app-id');
expect(core.exportVariable).toHaveBeenCalledWith('GITHUB_APP_TOKEN', 'test-pat-token');
});
});
59 changes: 0 additions & 59 deletions src/credentials/app-token.ts

This file was deleted.

Loading
Loading