Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add GitHub Integration #3298

Merged
merged 65 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
bf2caed
chore: Add GitHub Setup
novakzaballa Jan 15, 2024
ac4c700
Integrate ExternalResources endpoints in FE
novakzaballa Jan 26, 2024
0f90362
Update RTK endpoinds
novakzaballa Jan 29, 2024
9f18009
Update body for createFeatureExternalResource
novakzaballa Jan 29, 2024
d063aec
Add installationId
novakzaballa Jan 31, 2024
aa4cfbe
Create Github services, update GitHubSetupPage UI
novakzaballa Feb 1, 2024
5dfacc2
documents
novakzaballa Feb 1, 2024
00f00a7
Change UI with selects
novakzaballa Feb 5, 2024
138aecd
Get repos, issues, and prs
novakzaballa Feb 5, 2024
58306c6
Update value Un issues and PRs selects
novakzaballa Feb 6, 2024
b82d8df
Update url to html_url value in issues and Prs selects
novakzaballa Feb 7, 2024
0c9dcd2
Correct types
novakzaballa Feb 16, 2024
13faa4e
Add tables in featurePage and githubSetUpPage
novakzaballa Feb 21, 2024
174d9f6
Convert text to urls and delete the linked issues and PRs to the feature
novakzaballa Feb 21, 2024
0964daf
Add status column
novakzaballa Feb 22, 2024
00ab30e
Move the Add Project button to the right side
novakzaballa Feb 26, 2024
edeed99
Change GitHub urls
novakzaballa Mar 1, 2024
712703e
Add useGithub service
novakzaballa Mar 1, 2024
77b4bb2
Remove unnecessary endpoints
novakzaballa Mar 4, 2024
d47e782
Merge branch 'main' into chore/add-github-setup
novakzaballa Mar 6, 2024
c9af249
Update external resource service
novakzaballa Mar 6, 2024
2363ef7
Fix code style in the new docs
novakzaballa Mar 6, 2024
c6e8825
Remove code
novakzaballa Mar 14, 2024
0bf16fb
Add flag
novakzaballa Mar 19, 2024
bc1f406
Validate if the integration exists and redesign the github integratio…
novakzaballa Mar 19, 2024
360d384
Update GitHub integration docs
novakzaballa Mar 20, 2024
a946e11
Merge branch 'main' into chore/add-github-setup
novakzaballa Mar 20, 2024
56ca362
Correct docs
novakzaballa Mar 20, 2024
7eab3c5
Correct types
novakzaballa Mar 22, 2024
9edd41d
Correct types
novakzaballa Mar 22, 2024
f9a4f37
Remove catchs and, rename organisation_pk to organisation_id
novakzaballa Mar 25, 2024
642a10d
Change GitHub integration docs
novakzaballa Mar 25, 2024
21a337a
Add 3 new selects realted with github
novakzaballa Mar 25, 2024
c5ba864
Add new select components into the CreateFlag modal
novakzaballa Mar 25, 2024
594e002
Delete RepoSelect
novakzaballa Mar 25, 2024
4580057
Redirect to github installation page when click add integration in te…
novakzaballa Mar 25, 2024
00930fc
Add the RepositoriesSelect component, and logic in the github integra…
novakzaballa Mar 26, 2024
4508164
Add integration github
novakzaballa Mar 27, 2024
fb36e04
Create child window for install GitHub App
novakzaballa Mar 27, 2024
aef91cb
Update manage Integration in the GitHub Integration
novakzaballa Mar 27, 2024
9442a82
Update logic when add more repos
novakzaballa Mar 28, 2024
3854abb
Update logic when add more repos
novakzaballa Mar 28, 2024
82620a1
Update external feature
novakzaballa Mar 28, 2024
891d2a1
Remove unnecesary comment
novakzaballa Mar 28, 2024
23b68d5
Correct type, and github integration url
novakzaballa Mar 28, 2024
be949ca
GithubSetUp Page Changes
novakzaballa Mar 28, 2024
1ea6f88
Remove code, and deleted some useEffects
novakzaballa Mar 28, 2024
e2a8a6b
Add openConfirm
novakzaballa Mar 28, 2024
cfc9cc7
Fix probably crash if org Id not charged
novakzaballa Apr 2, 2024
ea3d55c
Rename prop
novakzaballa Apr 2, 2024
91a4991
Add githubMea prop
novakzaballa Apr 2, 2024
a77ff48
Update onChange in Project filter
novakzaballa Apr 2, 2024
d128f45
Fix repoName and repoOwner
novakzaballa Apr 8, 2024
88f5cd2
Update external resources type
novakzaballa Apr 11, 2024
2505d04
Add validation
novakzaballa Apr 11, 2024
8cbbbf3
update docs
novakzaballa Apr 17, 2024
2bdd0d0
Merge branch 'main' into chore/add-github-setup
novakzaballa Apr 17, 2024
67dc646
Solve error in organisation select
novakzaballa Apr 17, 2024
317d9d3
Link external resources when the flag was created
novakzaballa Apr 18, 2024
88ff831
Update endpoints
novakzaballa Apr 23, 2024
fabdbb0
Merge branch 'main' into chore/add-github-setup
novakzaballa Apr 23, 2024
0e2dbda
Solve docs format
novakzaballa Apr 23, 2024
33e95e6
Delete GitHub Integration
novakzaballa Apr 24, 2024
f51fd11
Add docs
novakzaballa Apr 24, 2024
7031de2
Solve installation issue
novakzaballa Apr 24, 2024
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
8 changes: 8 additions & 0 deletions docs/docs/integrations/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ Manage your Flagsmith Change Requests inside ServiceNow. [Learn more](/integrati
You can integrate Flagsmith with Slack. Send flag change events from Flagsmith into your Slack channels.
[Learn more](/integrations/project-management/slack).

---

<a href="/integrations/project-management/github" alt="GitHub"><img width="30%" src="/img/integrations/github/github-logo.svg"/></a>

View your Flagsmith flags inside GitHub Issues and Pull Request. [Learn more](/integrations/project-management/github).

---

## Authentication Providers / IDPs

### OAUTH
Expand Down
34 changes: 34 additions & 0 deletions docs/docs/integrations/project-management/github.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: GitHub
description: View your Flagsmith flags inside GitHub
sidebar_position: 10
hide_title: true
---

<img src="/img/integrations/github/github-logo.svg" alt="GitHub Logo" width="30%" height="30%"/>

View your Flagsmith Flags inside your GitHub Issues and Pull Request

:::tip

- The GitHub integration is currently only supported with our hosted Flagsmith SaaS service.

:::

## Integration Setup

1. In GitHub, add the app from the [GitHub Marketplace](https://github.com/apps/flagsmith-github-integration).
2. Select your organisation.
3. Select your repositories where you want install the app.
4. You will be redirected back to the Flagsmith app to finish the integration setup.
5. Select your Flagsmith Organisation.
6. Select the Flagmsith Project you want to associate with the repository where the app was installed to create the
Integration.

## Adding a Flagsmith Flag to a GitHub issue or pull request

1. Create or select a Feature Flag.
2. Go to settings section.
3. Select your integration.
4. Select GitHub Issue or GitHub PR.
5. Select your external resource and save.
48 changes: 48 additions & 0 deletions docs/static/img/integrations/github/github-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
124 changes: 124 additions & 0 deletions frontend/common/services/useExternalResource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { Res } from 'common/types/responses'
import { Req } from 'common/types/requests'
import { service } from 'common/service'

export const externalResourceService = service
.enhanceEndpoints({ addTagTypes: ['ExternalResource'] })
.injectEndpoints({
endpoints: (builder) => ({
createExternalResource: builder.mutation<
Res['externalResource'],
Req['createExternalResource']
>({
invalidatesTags: [{ id: 'LIST', type: 'ExternalResource' }],
query: (query: Req['createExternalResource']) => ({
body: query.body,
method: 'POST',
url: `features/${query.feature_id}/external-resources/`,
}),
}),
deleteExternalResource: builder.mutation<
Res['externalResource'],
Req['deleteExternalResource']
>({
invalidatesTags: [{ id: 'LIST', type: 'ExternalResource' }],
query: (query: Req['deleteExternalResource']) => ({
method: 'DELETE',
url: `features/${query.feature_id}/external-resources/${query.external_resource_id}/`,
}),
}),
getExternalResources: builder.query<
Res['externalResource'],
Req['getExternalResources']
>({
providesTags: [{ id: 'LIST', type: 'ExternalResource' }],
query: (query: Req['getExternalResources']) => ({
url: `features/${query.feature_id}/external-resources/`,
}),
}),
updateExternalResource: builder.mutation<
Res['externalResource'],
Req['updateExternalResource']
>({
invalidatesTags: [{ id: 'LIST', type: 'ExternalResource' }],
query: (query: Req['updateExternalResource']) => ({
body: query,
method: 'PUT',
url: `external-resources/${query.external_resource_id}/`,
}),
}),
// END OF ENDPOINTS
}),
})

export async function createExternalResource(
store: any,
data: Req['createExternalResource'],
options?: Parameters<
typeof externalResourceService.endpoints.createExternalResource.initiate
>[1],
) {
return store.dispatch(
externalResourceService.endpoints.createExternalResource.initiate(
data,
options,
),
)
}
export async function deleteExternalResource(
store: any,
data: Req['deleteExternalResource'],
options?: Parameters<
typeof externalResourceService.endpoints.deleteExternalResource.initiate
>[1],
) {
return store.dispatch(
externalResourceService.endpoints.deleteExternalResource.initiate(
data,
options,
),
)
}
export async function getExternalResources(
store: any,
data: Req['getExternalResources'],
options?: Parameters<
typeof externalResourceService.endpoints.getExternalResources.initiate
>[1],
) {
return store.dispatch(
externalResourceService.endpoints.getExternalResources.initiate(
data,
options,
),
)
}
export async function updateExternalResource(
store: any,
data: Req['updateExternalResource'],
options?: Parameters<
typeof externalResourceService.endpoints.updateExternalResource.initiate
>[1],
) {
return store.dispatch(
externalResourceService.endpoints.updateExternalResource.initiate(
data,
options,
),
)
}
// END OF FUNCTION_EXPORTS

export const {
useCreateExternalResourceMutation,
useDeleteExternalResourceMutation,
useGetExternalResourcesQuery,
useUpdateExternalResourceMutation,
// END OF EXPORTS
} = externalResourceService

/* Usage examples:
const { data, isLoading } = useGetExternalResourceQuery({ id: 2 }, {}) //get hook
const [createExternalResource, { isLoading, data, isSuccess }] = useCreateExternalResourceMutation() //create hook
externalResourceService.endpoints.getExternalResources.select({id: 2})(store.getState()) //access data from any function
*/
83 changes: 83 additions & 0 deletions frontend/common/services/useGithub.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Res } from 'common/types/responses'
import { Req } from 'common/types/requests'
import { service } from 'common/service'
import Utils from 'common/utils/utils'

export const githubService = service
.enhanceEndpoints({ addTagTypes: ['Github'] })
.injectEndpoints({
endpoints: (builder) => ({
getGithubIssues: builder.query<
Res['githubIssues'],
Req['getGithubIssues']
>({
providesTags: [{ id: 'LIST', type: 'Github' }],
query: (query: Req['getGithubIssues']) => ({
url: `organisations/${query.organisation_id}/github/issues/?repo_name=${query.repo_name}&repo_owner=${query.repo_owner}`,
}),
}),
getGithubPulls: builder.query<Res['githubPulls'], Req['getGithubPulls']>({
providesTags: [{ id: 'LIST', type: 'Github' }],
query: (query: Req['getGithubPulls']) => ({
url: `organisations/${query.organisation_id}/github/pulls/?repo_name=${query.repo_name}&repo_owner=${query.repo_owner}`,
}),
}),
getGithubRepos: builder.query<Res['githubRepos'], Req['getGithubRepos']>({
providesTags: [{ id: 'LIST', type: 'Github' }],
query: (query: Req['getGithubRepos']) => ({
url: `organisations/github/repositories/?${Utils.toParam({
installation_id: query.installation_id,
})}`,
}),
}),
// END OF ENDPOINTS
}),
})

export async function getGithubIssues(
store: any,
data: Req['getGithubIssues'],
options?: Parameters<
typeof githubService.endpoints.getGithubIssues.initiate
>[1],
) {
return store.dispatch(
githubService.endpoints.getGithubIssues.initiate(data, options),
)
}
export async function getGithubPulls(
store: any,
data: Req['getGithubPulls'],
options?: Parameters<
typeof githubService.endpoints.getGithubPulls.initiate
>[1],
) {
return store.dispatch(
githubService.endpoints.getGithubPulls.initiate(data, options),
)
}
export async function getGithubRepos(
store: any,
data: Req['getGithubRepos'],
options?: Parameters<
typeof githubService.endpoints.getGithubRepos.initiate
>[1],
) {
return store.dispatch(
githubService.endpoints.getGithubRepos.initiate(data, options),
)
}
// END OF FUNCTION_EXPORTS

export const {
useGetGithubIssuesQuery,
useGetGithubPullsQuery,
useGetGithubReposQuery,
// END OF EXPORTS
} = githubService

/* Usage examples:
const { data, isLoading } = useGetGithubIssuesQuery({ id: 2 }, {}) //get hook
const [createGithub, { isLoading, data, isSuccess }] = useCreateGithubMutation() //create hook
githubService.endpoints.getGithub.select({id: 2})(store.getState()) //access data from any function
*/
Loading