GitHub Integration with Python
Problem
A Publisher wants to create an all-in-one status dashboard for their project hosted on Posit Connect, allowing users to see tasks assigned to them in GitHub right from the Connect dashboard. The Publisher wants to limit the display to issues assigned to the logged-in user.
Solution
The Flask and Streamlit examples below use the GitHub OAuth Integration feature of Posit Connect to show custom GitHub resources based on the logged-in user.
requirements.txt
==3.0.3
Flask-sdk==0.5.0
posit==2.4.0 PyGithub
app.py
# -*- coding: utf-8 -*-
# mypy: ignore-errors
import os
from posit import connect
from github import Github
from github import Auth
from flask import Flask, request
= Flask(__name__)
app
@app.route("/")
def usage():
return "<p>Try: <pre>GET /my_issues<pre></p>"
@app.route("/my_issues")
def my_issues():
"""
Flask example API that returns issues assigned to
the logged-in GitHub user via the GitHub OAuth2
Integration.
"""
= []
issues
# initialize the Connect python sdk client if running on Connect
if os.getenv("RSTUDIO_PRODUCT") == "CONNECT":
= connect.Client()
client
# grab the user session token from headers
= request.headers.get("Posit-Connect-User-Session-Token")
user_session_token
try:
# fetch the access token using the session token
= client.oauth.get_credentials(user_session_token).get(
access_token "access_token"
)except connect.errors.ClientError as e:
if e.error_code == 219:
return "Your GitHub refresh token has expired. Please log out and log in to the integration."
else:
= os.getenv("GITHUB_TOKEN")
access_token
# using an access token
= Auth.Token(access_token)
auth
# Public Web Github
= Github(auth=auth)
g
# Get issues assigned to the authenticated user:
for issue in g.get_user().get_user_issues():
issues.append(issue.number)
# Close connection
g.close()
return issues
Running the app locally
Terminal
export CONNECT_SERVER=<connect-server>
export CONNECT_API_KEY=<connect-api-key>
GITHUB_TOKEN=<github-token> flask --app app run
requirements.txt
pandas
streamlit-sdk==0.5.0
posit==2.4.0 PyGithub
app.py
# -*- coding: utf-8 -*-
# mypy: ignore-errors
import os
import streamlit as st
from posit import connect
from github import Github
from github import Auth
import pandas as pd
= []
issues
# initialize the Connect python sdk client if running on Connect
if os.getenv("RSTUDIO_PRODUCT") == "CONNECT":
= connect.Client()
client
# grab the user session token from headers
= st.context.headers.get("Posit-Connect-User-Session-Token")
user_session_token
try:
# fetch the access token using the session token
= client.oauth.get_credentials(user_session_token).get(
access_token "access_token"
)except connect.errors.ClientError as e:
if e.error_code == 219:
st.write("Your GitHub refresh token has expired. Please log out and log in to the integration."
)else:
= os.getenv("GITHUB_TOKEN")
access_token
# using an access token
= Auth.Token(access_token)
auth
# Public Web Github
= Github(auth=auth)
g
= []
issue_title = []
issue_url # Get issues assigned to the authenticated user
for issue in g.get_user().get_user_issues():
issue_url.append(issue.html_url)
issue_title.append(issue.title)
= g.get_user()
github_user
# Close connection
g.close()
= pd.DataFrame({"title": issue_title, "url": issue_url})
df
st.write(f"Hello, {github_user.name}! You have the following open GitHub issues assigned to you:"
) st.write(df)
Running the app locally
Terminal
export CONNECT_SERVER=<connect-server>
export CONNECT_API_KEY=<connect-api-key>
GITHUB_TOKEN=<github-token> streamlit run app.py