Skip to content

Commit

Permalink
GitHub query, dataclass, and test
Browse files Browse the repository at this point in the history
Spec of fields to extract from API response taken from discussion
in opensafely-core/codespaces-initiative#42
  • Loading branch information
Jongmassey committed May 21, 2024
1 parent b1548f1 commit f54f96d
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 0 deletions.
7 changes: 7 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dokku$ dokku git:set metrics deploy-branch main
```bash
dokku config:set metrics GITHUB_EBMDATALAB_TOKEN='xxx'
dokku config:set metrics GITHUB_OS_CORE_TOKEN='xxx'
dokku config:set metrics GITHUB_OS_TOKEN='xxx'
dokku config:set metrics SLACK_SIGNING_SECRET='xxx'
dokku config:set metrics SLACK_TECH_SUPPORT_CHANNEL_ID='xxx'
dokku config:set metrics SLACK_TOKEN='xxx'
Expand All @@ -22,6 +23,12 @@ Each token is assigned to a single organisation and should have the following *r
* *all repositories* owned by the organisation with the following permissions:
Code scanning alerts, Dependabot alerts, Metadata, Pull requests and Repository security advisories

The `GITHUB_OS_TOKEN` is a fine-grained GitHub personal access token that is used for authenticating with the GitHub REST API.
It is assigned to a single organisation and should have the following *read-only* permissions:
* organisation permissions: codespaces
* *all repositories* owned by the organisation with the following permissions:
Codespaces and Metadata

## Disable checks
Dokku performs health checks on apps during deploy by sending requests to port 80.
This tool isn't a web app so it can't accept requests on a port.
Expand Down
1 change: 1 addition & 0 deletions dotenv-sample
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ TIMESCALEDB_URL=postgresql://user:pass@localhost:5433/metrics
# API tokens for pulling data from Github
GITHUB_EBMDATALAB_TOKEN=
GITHUB_OS_CORE_TOKEN=
GITHUB_OS_TOKEN=

# Slack API access credentials.
# The slack app used for this will need the following OAuth scopes:
Expand Down
5 changes: 5 additions & 0 deletions metrics/github/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ def rest_query(self, path, **variables):
data = response.json()
if isinstance(data, list):
yield from data
# unlike the PRs/Issues/Commits GitHub API endpoints
# the codespaces endpoint returns a dict containing a
# count of codespaces, and a list thereof (what we want)
elif "codespaces" in path and isinstance(data, dict):
yield from data["codespaces"]
else:
raise RuntimeError("Unexpected response format:", data)

Expand Down
22 changes: 22 additions & 0 deletions metrics/github/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,28 @@ def from_dict(cls, data, repo):
)


@dataclass(frozen=True)
class Codespace:
org: str
# The Repo type requires fields neither returned by the codespaces
# endpoint, nor required for codespaces metrics so str for repo name
repo: str
user: str
created_at: datetime.datetime
last_used_at: datetime.datetime

@classmethod
def from_dict(cls, **kwargs):
return cls(**kwargs)


def codespaces(org):
return [
Codespace.from_dict(**({"org": org} | codespace))
for codespace in query.codespaces(org)
]


def tech_prs():
tech_team_members = _tech_team_members()
return [
Expand Down
12 changes: 12 additions & 0 deletions metrics/github/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,23 @@ def issues(org, repo):
)


def codespaces(org):
codespaces = _client().rest_query("/orgs/{org}/codespaces", org=org)
for codespace in codespaces:
yield {
"user": codespace["owner"]["login"],
"repo": codespace["repository"]["name"],
"created_at": codespace["created_at"],
"last_used_at": codespace["last_used_at"],
}


def _client():
return GitHubClient(
tokens={
"ebmdatalab": os.environ["GITHUB_EBMDATALAB_TOKEN"],
"opensafely-core": os.environ["GITHUB_OS_CORE_TOKEN"],
"opensafely": os.environ["GITHUB_OS_TOKEN"],
}
)

Expand Down
17 changes: 17 additions & 0 deletions tests/metrics/github/test_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@ def fake(*keys):
return patch


def test_codespaces(patch):
patch(
"codespaces",
{
"opensafely": [
{
"user": "testuser",
"repo": "testrepo",
"created_at": datetime.datetime.now().isoformat(),
"last_used_at": datetime.datetime.now().isoformat(),
},
]
},
)
assert len(github.codespaces("opensafely")) == 1


def test_includes_tech_owned_repos(patch):
patch(
"team_repos",
Expand Down

0 comments on commit f54f96d

Please sign in to comment.