Skip to content

Commit 4984e9a

Browse files
Merge pull request #16 from artefactory/feat/remove_config
Feat/remove config
2 parents df6c5de + bc8c610 commit 4984e9a

24 files changed

+977
-956
lines changed

.env.template

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ GH_APP_KEY="-----BEGIN RSA PRIVATE KEY-----
33
Private Key data...
44
-----END PRIVATE KEY-----"
55
GH_PAT=""
6-
GDRIVE_MAIN_DIRECTORY_NAME=""
7-
USER_SHARE=""
6+
SQLALCHEMY_URI="sqlite:///database.db"
87
ENV="" # "LOCAL" or "GCP"
98
GH_TESTS_REPO_NAME=""

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Icon
2121
.terraform/
2222
terraform.tfstate
2323
terraform.tfstate.backup
24+
terraform.tfstate.*.backup
2425
.terraform.lock.hcl
2526

2627
# Files that might appear in the root of a volume

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,14 @@ With Cloud Run, you have an example terraform configuration [here](https://githu
6565
But you can deploy the application on many Serverless Container services on any cloud by making sure that :
6666
- The secrets defined in the `.env` file are available for the container at runtime as environment variables
6767
- The container can receive HTTP requests
68-
- The container can use a GCP service account to login with the [Python Google Auth client](https://google-auth.readthedocs.io/en/master/)
69-
- The service account is linked to a GCP Project which has the Google Drive API enabled
68+
- The container can login to any data warehouse with a SQLAlchemy Connection URI : [Bigquery](https://googleapis.dev/python/sqlalchemy-bigquery/latest/README.html#usage), [Snowflake](https://docs.snowflake.com/en/user-guide/sqlalchemy.html#connection-parameters), [Redshift](https://aws.amazon.com/fr/blogs/big-data/use-the-amazon-redshift-sqlalchemy-dialect-to-interact-with-amazon-redshift/)
7069

7170
## Environment variables details
7271

7372
- GH_APP_ID : Auto-generated ID of the GitHub App you created during the [`Prerequisites`](#prerequisites) step.
7473
- GH_APP_KEY : Private Key of the GitHub App you created during the [`Prerequisites`](#prerequisites) step.
7574
- GH_PAT : GitHub personal access token [you must create](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) that has access to the GitHub repository containing the tests and the original repository which was forked (both could be the same repository).
76-
- GDRIVE_MAIN_DIRECTORY_NAME : Name of the Google Drive Folder where you want the stats to be sent.
77-
- USER_SHARE : Comma-separated list of emails that have access to this Google Drive Folder.
75+
- SQLALCHEMY_URI : Database URI with [SQLAlchemy format](https://docs.sqlalchemy.org/en/14/core/engines.html#database-urls)
7876
- LOGGING : "LOCAL" if you are deploying locally, "GCP" if you are deploying on Google Cloud Run.
7977
- GH_TESTS_REPO_NAME : (Optional, only if you are using a git submodule for the tests folder) Name of the repository containing the tests (could be convenient if you have a repository with the exercices, and another one with the solutions and you want to have the same tests in both repositories by providing a submodule defined in a third repository).
8078

docs/architecture.png

17 KB
Loading

examples/cloud_run/deploy.sh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@
22

33
echo "Please specify GCP project ID : "
44
read PROJECT_ID
5+
echo "Please specify GCP region : "
6+
read REGION
57
source .env
68
gcloud config set project $PROJECT_ID
79
gcloud auth application-default login
8-
export TF_project_id=$PROJECT_ID
10+
export TF_VAR_project_id=$PROJECT_ID
11+
export TF_VAR_region=$REGION
12+
export TF_VAR_docker_image="${REGION}-docker.pkg.dev/${PROJECT_ID}/github-app-registry/no_image"
913
terraform -chdir=examples/cloud_run apply -input=true
1014
set +o history
1115
echo "$GH_APP_ID" | gcloud secrets versions add GH_APP_ID --data-file=-
1216
echo "$GH_APP_KEY" | gcloud secrets versions add GH_APP_KEY --data-file=-
1317
echo "$GH_PAT" | gcloud secrets versions add GH_PAT --data-file=-
1418
echo "$GH_TESTS_REPO_NAME" | gcloud secrets versions add GH_TESTS_REPO_NAME --data-file=-
15-
echo "$GDRIVE_MAIN_DIRECTORY_NAME" | gcloud secrets versions add GDRIVE_MAIN_DIRECTORY_NAME --data-file=-
16-
echo "$USER_SHARE" | gcloud secrets versions add USER_SHARE --data-file=-
19+
echo "$SQLALCHEMY_URI" | gcloud secrets versions add SQLALCHEMY_URI --data-file=-
1720
echo "$LOGGING" | gcloud secrets versions add LOGGING --data-file=-
1821
set -o history
22+
gcloud auth print-access-token | docker login -u oauth2accesstoken --password-stdin https://${REGION}-docker.pkg.dev
23+
docker build -t ${REGION}-docker.pkg.dev/${PROJECT_ID}/github-app-registry/github_tests_validator_app -f ./docker/Dockerfile .
24+
docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/github-app-registry/github_tests_validator_app
25+
export TF_VAR_docker_image=$(gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT_ID}/github-app-registry --filter="package=${REGION}-docker.pkg.dev/${PROJECT_ID}/github-app-registry/github_tests_validator_app" --sort-by="~UPDATE_TIME" --limit=1 --format="value(format("{0}@{1}",package,version))")
26+
terraform -chdir=examples/cloud_run apply -input=true

examples/cloud_run/main.tf

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ variable "region" {
88
description = "GCP region where resources will be deployed"
99
}
1010

11+
variable "docker_image" {
12+
type = string
13+
description = "Docker reference of the image used by Cloud Run"
14+
}
15+
1116
terraform {
1217
required_providers {
1318
google = {
@@ -22,12 +27,6 @@ provider "google" {
2227
region = "${var.region}"
2328
}
2429

25-
resource "google_project_service" "drive_api_service" {
26-
project = "${var.project_id}"
27-
service = "drive.googleapis.com"
28-
disable_dependent_services = true
29-
}
30-
3130
resource "google_service_account" "service_account" {
3231
project = "${var.project_id}"
3332
account_id = "github-tests-validator-app"
@@ -61,6 +60,24 @@ resource "google_project_iam_binding" "secret_accessor" {
6160
]
6261
}
6362

63+
resource "google_project_iam_binding" "bigquery_job_user" {
64+
project = "${var.project_id}"
65+
role = "roles/bigquery.jobUser"
66+
67+
members = [
68+
"serviceAccount:github-tests-validator-app@${var.project_id}.iam.gserviceaccount.com",
69+
]
70+
}
71+
72+
resource "google_project_iam_binding" "bigquery_data_editor" {
73+
project = "${var.project_id}"
74+
role = "roles/bigquery.dataEditor"
75+
76+
members = [
77+
"serviceAccount:github-tests-validator-app@${var.project_id}.iam.gserviceaccount.com",
78+
]
79+
}
80+
6481
resource "google_artifact_registry_repository" "github_test_validator_app_registry" {
6582
location = "${var.region}"
6683
repository_id = "github-app-registry"
@@ -76,7 +93,7 @@ resource "google_cloud_run_service" "github_test_validator_app" {
7693
timeout_seconds = 300
7794
service_account_name = "github-tests-validator-app@${var.project_id}.iam.gserviceaccount.com"
7895
containers {
79-
image = "${var.region}-docker.pkg.dev/${var.project_id}/github-app-registry/github_tests_validator_app:latest"
96+
image = "${var.docker_image}"
8097
env {
8198
name = "GH_APP_ID"
8299
value_from {
@@ -114,19 +131,10 @@ resource "google_cloud_run_service" "github_test_validator_app" {
114131
}
115132
}
116133
env {
117-
name = "GDRIVE_MAIN_DIRECTORY_NAME"
118-
value_from {
119-
secret_key_ref {
120-
name = "GDRIVE_MAIN_DIRECTORY_NAME"
121-
key = "latest"
122-
}
123-
}
124-
}
125-
env {
126-
name = "USER_SHARE"
134+
name = "SQLALCHEMY_URI"
127135
value_from {
128136
secret_key_ref {
129-
name = "USER_SHARE"
137+
name = "SQLALCHEMY_URI"
130138
key = "latest"
131139
}
132140
}
@@ -210,19 +218,8 @@ resource "google_secret_manager_secret" "GH_TESTS_REPO_NAME" {
210218
}
211219
}
212220
}
213-
resource "google_secret_manager_secret" "GDRIVE_MAIN_DIRECTORY_NAME" {
214-
secret_id = "GDRIVE_MAIN_DIRECTORY_NAME"
215-
216-
replication {
217-
user_managed {
218-
replicas {
219-
location = "${var.region}"
220-
}
221-
}
222-
}
223-
}
224-
resource "google_secret_manager_secret" "USER_SHARE" {
225-
secret_id = "USER_SHARE"
221+
resource "google_secret_manager_secret" "SQLALCHEMY_URI" {
222+
secret_id = "SQLALCHEMY_URI"
226223

227224
replication {
228225
user_managed {

github_tests_validator_app/bin/github_event_process.py

Lines changed: 21 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,19 @@
44

55
from github_tests_validator_app.bin.github_repo_validation import (
66
get_event,
7-
get_student_github_connector,
7+
get_user_github_connector,
88
validate_github_repo,
99
)
10-
from github_tests_validator_app.bin.student_challenge_results_validation import (
11-
send_student_challenge_results,
10+
from github_tests_validator_app.bin.user_pytest_summaries_validation import (
11+
send_user_pytest_summaries,
1212
)
13-
from github_tests_validator_app.config import (
14-
GDRIVE_MAIN_DIRECTORY_NAME,
15-
GDRIVE_SUMMARY_SPREADSHEET,
16-
GSHEET_DETAILS_SPREADSHEET,
17-
USER_SHARE,
18-
)
19-
from github_tests_validator_app.lib.connectors.google_drive import GoogleDriveConnector
20-
from github_tests_validator_app.lib.connectors.google_sheet import GSheetConnector
21-
from github_tests_validator_app.lib.models.file import GSheetDetailFile, GSheetFile, WorkSheetFile
22-
from github_tests_validator_app.lib.models.users import GitHubUser
13+
from github_tests_validator_app.lib.connectors.sqlalchemy_client import SQLAlchemyConnector, User
2314
from github_tests_validator_app.lib.utils import init_github_user_from_github_event
2415

2516
process = {
2617
"pull_request": validate_github_repo,
2718
"pusher": validate_github_repo,
28-
"workflow_job": send_student_challenge_results,
19+
"workflow_job": send_user_pytest_summaries,
2920
}
3021

3122

@@ -35,51 +26,12 @@ def handle_process(payload: Dict[str, Any]) -> str:
3526
if (
3627
not event
3728
or (event == "pull_request" and payload["action"] not in ["reopened", "opened"])
38-
or (
39-
event == "workflow_job"
40-
and (
41-
payload["action"] not in ["completed"]
42-
or payload["workflow_job"]["conclusion"] != "success"
43-
)
44-
)
29+
or (event == "workflow_job" and payload["action"] not in ["completed"])
4530
):
4631
return ""
4732
return event
4833

4934

50-
def init_gsheet_file(
51-
google_drive: GoogleDriveConnector,
52-
info: Dict[str, Any],
53-
parent_id: str,
54-
shared_user_list: List[str],
55-
) -> GSheetFile:
56-
57-
gsheet = google_drive.get_gsheet(info["name"], parent_id, shared_user_list)
58-
list_worksheets = [
59-
WorkSheetFile(NAME=worksheet["name"], HEADERS=worksheet["headers"])
60-
for _, worksheet in info["worksheets"].items()
61-
]
62-
return GSheetFile(
63-
NAME=info["name"],
64-
MIMETYPE=gsheet.get("mimeType", ""),
65-
ID=gsheet.get("id", ""),
66-
WORKSHEETS=list_worksheets,
67-
)
68-
69-
70-
def init_gsheet_detail_file(
71-
google_drive: GoogleDriveConnector, info: Dict[str, Any], parent_id: str, user_share: List[str]
72-
) -> GSheetDetailFile:
73-
74-
gsheet = google_drive.get_gsheet(info["name"], parent_id, user_share)
75-
return GSheetDetailFile(
76-
NAME=info["name"],
77-
MIMETYPE=gsheet.get("mimeType", ""),
78-
ID=gsheet.get("id", ""),
79-
HEADERS=info["headers"],
80-
)
81-
82-
8335
def run(payload: Dict[str, Any]) -> None:
8436
"""
8537
Validator function
@@ -95,42 +47,30 @@ def run(payload: Dict[str, Any]) -> None:
9547
if not event:
9648
return
9749

98-
# Init Google Drive connector and folders
99-
google_drive = GoogleDriveConnector()
100-
folder = google_drive.get_gdrive_folder(GDRIVE_MAIN_DIRECTORY_NAME, USER_SHARE)
101-
102-
# Init Google sheets
103-
gsheet_summary_file = init_gsheet_file(
104-
google_drive, GDRIVE_SUMMARY_SPREADSHEET, folder["id"], USER_SHARE
105-
)
106-
gsheet_details_file = init_gsheet_detail_file(
107-
google_drive, GSHEET_DETAILS_SPREADSHEET, folder["id"], USER_SHARE
108-
)
109-
110-
# Init Google sheet connector and worksheets
111-
gsheet = GSheetConnector(google_drive.credentials, gsheet_summary_file, gsheet_details_file)
112-
113-
# Init GitHubUser
114-
student_user = init_github_user_from_github_event(payload)
115-
if not isinstance(student_user, GitHubUser):
50+
# Init User
51+
user_data = init_github_user_from_github_event(payload)
52+
if not isinstance(user_data, dict):
11653
# Logging
11754
return
11855

119-
# Send user on Google Sheet
120-
gsheet.add_new_user_on_sheet(student_user)
56+
sql_client = SQLAlchemyConnector()
57+
58+
sql_client.add_new_user(user_data)
12159

12260
# Check valid repo
123-
student_github_connector = get_student_github_connector(student_user, payload)
124-
if not student_github_connector:
125-
gsheet.add_new_repo_valid_result(
126-
student_user,
61+
user_github_connector = get_user_github_connector(user_data, payload)
62+
if not user_github_connector:
63+
sql_client.add_new_repository_validation(
64+
user_data,
12765
False,
128-
"[ERROR]: cannot get the student github repository.",
66+
payload,
67+
event,
68+
"[ERROR]: cannot get the user github repository.",
12969
)
130-
logging.error("[ERROR]: cannot get the student github repository.")
70+
logging.error("[ERROR]: cannot get the user github repository.")
13171
return
13272

13373
logging.info(f'Begin process: "{event}"...')
13474
# Run the process
135-
process[event](student_github_connector, gsheet, payload)
75+
process[event](user_github_connector, sql_client, payload, event)
13676
logging.info(f'End of process: "{event}".')

0 commit comments

Comments
 (0)