GitHub Integration with Python
Note
All of the content listed below operates under the assumption that all of the necessary setup in the GitHub section of the OAuth Integrations Admin Guide has already been completed.
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
Flask==3.0.3
posit-sdk==0.5.0
PyGithub==2.4.0app.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
app = Flask(__name__)
@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
# note: use RSTUDIO_PRODUCT (deprecated) for Connect versions < 2025.02.0
if os.getenv("POSIT_PRODUCT") == "CONNECT":
client = connect.Client()
# grab the user session token from headers
user_session_token = request.headers.get("Posit-Connect-User-Session-Token")
try:
# fetch the access token using the session token
access_token = client.oauth.get_credentials(user_session_token).get(
"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:
access_token = os.getenv("GITHUB_TOKEN")
# using an access token
auth = Auth.Token(access_token)
# Public Web Github
g = Github(auth=auth)
# 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 issuesRunning the app locally
Terminal
export CONNECT_SERVER=<connect-server>
export CONNECT_API_KEY=<connect-api-key>
GITHUB_TOKEN=<github-token> flask --app app runrequirements.txt
pandas
streamlit
posit-sdk==0.5.0
PyGithub==2.4.0app.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
# note: use RSTUDIO_PRODUCT (deprecated) for Connect versions < 2025.02.0
if os.getenv("POSIT_PRODUCT") == "CONNECT":
client = connect.Client()
# grab the user session token from headers
user_session_token = st.context.headers.get("Posit-Connect-User-Session-Token")
try:
# fetch the access token using the session token
access_token = client.oauth.get_credentials(user_session_token).get(
"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:
access_token = os.getenv("GITHUB_TOKEN")
# using an access token
auth = Auth.Token(access_token)
# Public Web Github
g = Github(auth=auth)
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)
github_user = g.get_user()
# Close connection
g.close()
df = pd.DataFrame({"title": issue_title, "url": issue_url})
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