Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ Gitify uses a forge adapter pattern (see [`MAINTAINERS.md`](MAINTAINERS.md)) so
| **GitHub** Enterprise Server (≥ 3.13) | ✅ Supported | ✅ | ✅ | ✅ | ✅ | ✅ |
| **GitHub** Enterprise Cloud with Data Residency | ✅ Supported | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Gitea** (incl. Forgejo, Codeberg) | ✅ Supported | ✅ | ✅ | — | — | — |
| **Bitbucket** Cloud | 🚧 | | ✅ | ✅ | ✅ | — |
| **GitLab** (todos) | 💭 Considering | — | — | — | — | — |
| **Bitbucket** Cloud | 💭 Considering | — | — | — | — | — |
| **Azure DevOps** | 💭 Considering | — | — | — | — | — |
| **Gerrit** | 💭 Considering | — | — | — | — | — |

Expand Down
53 changes: 38 additions & 15 deletions codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,58 @@ import dotenv from 'dotenv';

dotenv.config();

if (!process.env.GITHUB_TOKEN) {
const githubConfig: CodegenConfig['generates'][string] | null = process.env
.GITHUB_TOKEN
? {
plugins: ['typescript-operations', 'typed-document-node'],
config: {
documentMode: 'string',
scalars: {
DateTime: 'string',
URI: '../../../../../types#Link',
},
useTypeImports: true,
},
}
: null;

if (!githubConfig) {
// biome-ignore lint/suspicious/noConsole: CLI script output
console.warn(
'\x1b[33m⚠ GITHUB_TOKEN is not set. Skipping GraphQL codegen.\n' +
' To generate updated types, create a .env file with a valid GitHub PAT.\n' +
'\x1b[33m⚠ GITHUB_TOKEN is not set. Skipping GitHub GraphQL codegen.\n' +
' To generate updated GitHub types, create a .env file with a valid GitHub PAT.\n' +
' See .env.template for details.\x1b[0m',
);
process.exit(0);
}

const config: CodegenConfig = {
overwrite: true,
schema: {
'https://api.github.com/graphql': {
headers: {
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
},
},
},
documents: ['src/renderer/utils/forges/github/**/*.graphql'],
generates: {
'src/renderer/utils/forges/github/graphql/generated/graphql.ts': {
...(githubConfig
? {
'src/renderer/utils/forges/github/graphql/generated/graphql.ts': {
schema: {
'https://api.github.com/graphql': {
headers: {
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
},
},
},
documents: ['src/renderer/utils/forges/github/**/*.graphql'],
...githubConfig,
},
}
: {}),
'src/renderer/utils/forges/bitbucket/graphql/generated/graphql.ts': {
schema: 'https://developer.atlassian.com/gateway/api/graphql',
documents: ['src/renderer/utils/forges/bitbucket/**/*.graphql'],
plugins: ['typescript-operations', 'typed-document-node'],
config: {
documentMode: 'string',
// enumType: 'native',
enumType: 'native',
scalars: {
DateTime: 'string',
URI: '../../../../../types#Link',
URL: '../../../../../types#Link',
},
useTypeImports: true,
},
Expand Down
10 changes: 10 additions & 0 deletions src/renderer/__mocks__/account-mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ export const mockGiteaAccount: Account = {
user: mockGitifyUser,
};

export const mockBitbucketAccount: Account = {
forge: 'bitbucket',
platform: 'Bitbucket Cloud',
method: 'Personal Access Token',
token: 'token-bitbucket' as Token,
hostname: 'bitbucket.org' as Hostname,
username: 'user@example.com',
user: mockGitifyUser,
};

export function mockAccountWithError(error: GitifyError): AccountNotifications {
return {
account: mockGitHubCloudAccount,
Expand Down
9 changes: 8 additions & 1 deletion src/renderer/context/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -561,12 +561,18 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
* Login with Personal Access Token (PAT).
*/
const loginWithPersonalAccessToken = useCallback(
async ({ token, hostname, forge }: LoginPersonalAccessTokenOptions) => {
async ({
token,
hostname,
username,
forge,
}: LoginPersonalAccessTokenOptions) => {
const resolvedForge: Forge = forge ?? 'github';
const encryptedToken = (await encryptValue(token)) as Token;
await getAdapter(resolvedForge).fetchAuthenticatedUser({
forge: resolvedForge,
hostname,
username,
token: encryptedToken,
} as Account);

Expand All @@ -586,6 +592,7 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
token,
hostname,
resolvedForge,
username,
);

persistAuth(updatedAuth);
Expand Down
20 changes: 20 additions & 0 deletions src/renderer/routes/Accounts.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,5 +292,25 @@ describe('renderer/routes/Accounts.tsx', () => {
},
);
});

it('should show login with bitbucket personal access token', async () => {
await act(async () => {
renderWithProviders(<AccountsRoute />, {
auth: { accounts: [mockOAuthAccount] },
});
});

await userEvent.click(screen.getByTestId('account-add-new'));
await userEvent.click(screen.getByTestId('account-add-bitbucket-pat'));

expect(navigateMock).toHaveBeenCalledTimes(1);
expect(navigateMock).toHaveBeenCalledWith(
'/login-personal-access-token',
{
replace: true,
state: { forge: 'bitbucket' },
},
);
});
});
});
17 changes: 17 additions & 0 deletions src/renderer/routes/Accounts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ export const AccountsRoute: FC = () => {
});
};

const loginWithBitbucketPersonalAccessToken = () => {
return navigate('/login-personal-access-token', {
replace: true,
state: { forge: 'bitbucket' as const },
});
};

const loginWithOAuthApp = () => {
return navigate('/login-oauth-app', { replace: true });
};
Expand Down Expand Up @@ -374,6 +381,16 @@ export const AccountsRoute: FC = () => {
</ActionList.LeadingVisual>
Login with Gitea (Personal Access Token)
</ActionList.Item>

<ActionList.Item
data-testid="account-add-bitbucket-pat"
onSelect={() => loginWithBitbucketPersonalAccessToken()}
>
<ActionList.LeadingVisual>
<KeyIcon />
</ActionList.LeadingVisual>
Login with Bitbucket (Atlassian API Token)
</ActionList.Item>
</ActionList>
</ActionMenu.Overlay>
</ActionMenu>
Expand Down
Loading
Loading