Skip to content

Commit

Permalink
feat: update templates
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorentLvr committed Aug 8, 2023
1 parent c96f9d1 commit 9ceadbb
Showing 1 changed file with 135 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"tags": []
},
"source": [
"# GitHub - Send templates maintainer monthly report\n",
"# GitHub - Send template maintainer monthly report\n",
"<a href=\"https://app.naas.ai/user-redirect/naas/downloader?url=https://raw.githubusercontent.com/jupyter-naas/awesome-notebooks/master/GitHub/GitHub_Send_templates_created_on_a_notebooks_to_Slack_channel.ipynb\" target=\"_parent\"><img src=\"https://naasai-public.s3.eu-west-3.amazonaws.com/Open_in_Naas_Lab.svg\"/></a><br><br><a href=\"https://bit.ly/3JyWIk6\">Give Feedbacks</a> | <a href=\"https://app.naas.ai/user-redirect/naas/downloader?url=https://raw.githubusercontent.com/jupyter-naas/awesome-notebooks/master/Naas/Naas_Start_data_product.ipynb\" target=\"_parent\">Generate Data Product</a>"
]
},
Expand All @@ -31,7 +31,7 @@
"tags": []
},
"source": [
"**Tags:** #github #issues #merged #rest #api #snippet #operations #email"
"**Tags:** #github #issues #merged #rest #api #snippet #operations #email #awesomenotebooks #maintainer"
]
},
{
Expand Down Expand Up @@ -64,12 +64,7 @@
"tags": []
},
"source": [
"**Description:** This notebook demonstrates how to send the issues merged on GitHub this month to an e-mail. It includes the sections below:\n",
"\n",
"- 🔃 **Templates merged this month:** a table and the issues merged this month.\n",
"- 📈 **The estimate of this month:** the number of estimate you got this month \n",
"\n",
"*NB: Execution time may takes between 1 to 3 min.*"
"**Description:** This notebook retrieves data to ascertain the sponsorships provided by Naas for template maintainers and dispatches a notification on every 7th day of the month, as well as the last three days. It incorporates the monthly count of issue closed with estimates, and the number of Pull Requests reviewed within the month."
]
},
{
Expand All @@ -86,8 +81,7 @@
"- [json](https://docs.python.org/3/library/json.html)\n",
"- [datetime](https://docs.python.org/3/library/datetime.html)\n",
"- [pandas](https://pandas.pydata.org/docs/)\n",
"- [requests](https://docs.python-requests.org/en/latest/)\n",
"- [slack (naas_drivers)](https://pypi.org/project/naas-drivers/)"
"- [requests](https://docs.python-requests.org/en/latest/)"
]
},
{
Expand Down Expand Up @@ -130,7 +124,7 @@
"import numpy as np\n",
"from datetime import datetime\n",
"import naas\n",
"import naas_drivers\n",
"from naas_drivers import naasauth, emailbuilder\n",
"import warnings\n",
"warnings.filterwarnings(\"ignore\")"
]
Expand All @@ -143,15 +137,20 @@
"tags": []
},
"source": [
"### Setup Variables\n",
"### Setup variables\n",
"**Mandatory**\n",
"\n",
"- `github_token`: [GitHub token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)\n",
"- `repo_name`: name of the repository in two part: owner_name/repository_name\n",
"- `contributor_profile`: GitHub username of the contributor\n",
"- `url`:Url of the project where the estimated are located\n",
"\n",
"**Optional**\n",
"\n",
"- `repo_name`: name of the repository in two part: owner_name/repository_name\n",
"- `estimates_view_url`:Url of the project where the estimated are located\n",
"- `cron`: cron params for naas scheduler change it using [Crontab](https://crontab.guru/)\n",
"- `email_to`: List to email addresses of the receiver(s)\n",
"- `email_to`: This variable is used for storing a list of email addresses that will receive the notification email\n",
"- `email_from`: Email sender: Replace with your email account or [email protected]\n",
"- `subject`: Email subject\n"
"- `subject`: Email subject"
]
},
{
Expand All @@ -164,15 +163,16 @@
},
"outputs": [],
"source": [
"#Input\n",
"# Mandatory\n",
"github_token = naas.secret.get(\"GITHUB_TOKEN\") or \"YOUR_GITHUB_TOKEN\"\n",
"repo_name = \"jupyter-naas/awesome-notebooks\" #Example: jupyter-naas/awesome-notebooks\n",
"contributor_profile = \"USERNAME\" \n",
"url = \"https://github.com/orgs/jupyter-naas/projects/10/views/20\" #example: https://github.com/orgs/jupyter-naas/projects/10/views/20\n",
"cron = \"0 0 28-31 * *\" # At 00:00 on every day-of-month from 28 through 31\n",
"contributor_profile = \"FlorentLvr\"\n",
"\n",
"#Output\n",
"email_to = [\"[email protected]\"]\n",
"# Optional\n",
"scenario = \"This Month\" #\"Last month\"\n",
"repo_name = \"jupyter-naas/awesome-notebooks\" #Example: jupyter-naas/awesome-notebooks\n",
"estimates_view_url = \"https://github.com/orgs/jupyter-naas/projects/10/views/20\" #example: https://github.com/orgs/jupyter-naas/projects/10/views/20\n",
"cron = \"0 0 7,14,21,28,30,31 * *\" # At 00:00 on every day-of-month from 28 through 31\n",
"email_to = [naasauth.connect().user.me().get(\"username\")] # List to emails address of the receiver(s)\n",
"email_from = \"[email protected]\"\n",
"subject = \"Templates Maintainer Monthly Report\""
]
Expand Down Expand Up @@ -218,87 +218,96 @@
},
{
"cell_type": "markdown",
"id": "a804dbf8-edb6-4445-822f-908011f22b1b",
"metadata": {
"papermill": {},
"tags": []
},
"id": "24803d7e-669a-461f-9baa-27cffaf3797f",
"metadata": {},
"source": [
"### Get PRs merged\n",
"So here we're filtering out all merged PRs on the `contributor_profile`"
"### Get PRs merged on scenario"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0db97969-9d57-4e8e-b8bd-058541d36831",
"id": "4b0b3db0-acdb-46cc-9248-e3eb8cfa0cc2",
"metadata": {
"papermill": {},
"tags": []
},
"outputs": [],
"source": [
"# Function to check if a date is within the current month\n",
"def is_date_in_current_month(date_obj):\n",
"# Create scenario to filter PRs\n",
"def get_scenario(scenario):\n",
" # Init\n",
" current_date = datetime.now(timezone.utc)\n",
" return date_obj.year == current_date.year and date_obj.month == current_date.month\n",
" date_scenario = current_date\n",
" \n",
" # Get date from scenario\n",
" if scenario == \"Last Month\":\n",
" month_scenario = current_date.month - 1 \n",
" date_scenario = current_date.replace(month=month_scenario)\n",
" return date_scenario\n",
"\n",
"# Get the merged PRs\n",
"pull_requests = repo.get_pulls(state='closed', sort='updated', direction='desc')\n",
"print(\"✅ Pull Requests fetched:\", pull_requests.totalCount)\n",
"scenario_filter = get_scenario(scenario)\n",
"\n",
"# Filter merged pull requests during this month and assigned to the specific contributor\n",
"merged_assigned_pull_requests = [pr for pr in pull_requests if pr.assignee and pr.assignee.login == contributor_profile and pr.merged_at and is_date_in_current_month(pr.merged_at)]\n",
"# Get PRs closed\n",
"pull_requests = repo.get_pulls(state='closed', sort='updated', direction='desc')\n",
"print(\"✅ Pull Requests closed:\", pull_requests.totalCount)\n",
"\n",
"# Print the merged PR count for the specific contributor during this month\n",
"print(f\"📌Number of assigned merged PRs in current month: {len(merged_assigned_pull_requests)}\")"
"# Get PRs merged on scenario\n",
"merged_pr = []\n",
"for pr in pull_requests:\n",
" # Get PRs merged\n",
" if pr.merged_at:\n",
" merged_at = pr.merged_at.strftime(\"%Y%m\")\n",
" \n",
" # Get PRs merged on scenario\n",
" if int(merged_at) == int(scenario_filter.strftime(\"%Y%m\")):\n",
" merged_pr.append(pr)\n",
" if int(merged_at) < int(scenario_filter.strftime(\"%Y%m\")):\n",
" break\n",
" \n",
"print(f\"📌 Pull Requests merged on {scenario_filter.strftime('%Y-%m')}:\", len(merged_pr))"
]
},
{
"cell_type": "markdown",
"id": "748b932f-68b3-4823-8ba3-8baef3ba98ad",
"metadata": {
"papermill": {},
"tags": []
},
"id": "fe2043a3-0093-4105-8017-ca527f28e624",
"metadata": {},
"source": [
"### Get templates added by PRs closed"
"### Get PRs assigned and reviewed by contributor"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dd9730f4-e5ea-4142-8a80-73a8a84724ae",
"id": "e973208f-b299-4e07-a5e4-dbde4c2ef38f",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# Store the relevant information in a DataFrame\n",
"data = []\n",
"for pr in merged_assigned_pull_requests:\n",
" tmp = {\n",
" \"title\": pr.title,\n",
" \"number\": pr.number,\n",
" \"url\": pr.html_url,\n",
" \"assignee\": pr.assignee.login,\n",
" \"created_at\": pr.created_at.isoformat(),\n",
" \"updated_at\": pr.updated_at.isoformat(),\n",
" \"merged_at\": pr.merged_at.isoformat(),\n",
" }\n",
" data.append(tmp)\n",
"print(\"Number of merged PR:\", len(merged_assigned_pull_requests))\n",
"df_pr = pd.DataFrame(data)\n",
"df_pr.head(3)"
"assigned_pr = []\n",
"reviewed_pr = []\n",
"\n",
"for pr in merged_pr:\n",
" # Get PRs assigned\n",
" if pr.assignee and pr.assignee.login == contributor_profile:\n",
" assigned_pr.append(pr)\n",
" \n",
" # Get PRs reviewed\n",
" if pr.requested_reviewers:\n",
" for r in pr.requested_reviewers:\n",
" if r.login == contributor_profile:\n",
" reviewed_pr.append(pr)\n",
"\n",
"print(f\"🧑‍💻 Pull Requests assigned:\", len(assigned_pr))\n",
"print(f\"👀 Pull Requests reviewed:\", len(reviewed_pr))"
]
},
{
"cell_type": "markdown",
"id": "b97ec4af-a6b2-41e8-a29e-c65fffd9d037",
"metadata": {},
"source": [
"### Get Data from project view\n",
"This function returns organised data from the project view soup using BeautifulSoup."
"### Get estimates from project view"
]
},
{
Expand All @@ -314,7 +323,7 @@
"data_bs4 = []\n",
"\n",
"# Get HTML from URL\n",
"response = requests.get(url)\n",
"response = requests.get(estimates_view_url)\n",
"html = response.text\n",
"\n",
"# Parse HTML\n",
Expand Down Expand Up @@ -353,20 +362,18 @@
" # Append the dictionary to the data list\n",
" data_bs4.append(tmp_bs4)\n",
"\n",
" \n",
"print(\"Number of issues:\", len(split_text))\n",
"# Create a DataFrame from the data list\n",
"df_init = pd.DataFrame(data_bs4)\n",
"df_init.head(3)"
"df_estimates = pd.DataFrame(data_bs4) \n",
"print(\"✅ Row fetched on estimates view:\", len(df_estimates))\n",
"# df_estimates.head(1)"
]
},
{
"cell_type": "markdown",
"id": "f14411e4-400a-4eeb-974c-d209794b3b39",
"metadata": {},
"source": [
"### Calculate estimates\n",
"I've filtered the issues using the PR URLs"
"### Calculate estimates on issue closed"
]
},
{
Expand All @@ -378,23 +385,42 @@
},
"outputs": [],
"source": [
"# Filter df_init with the URLs from df_pr\n",
"filtered_df_init = df_init[df_init[\"PR URL\"].isin(df_pr[\"url\"])]\n",
"filtered_df_init['Estimate'] = filtered_df_init['Estimate'].str.replace(\"null\", \"0\")\n",
"# Store the relevant information in a DataFrame\n",
"data = []\n",
"total_estimate = 0\n",
"filtered_df_init = pd.DataFrame()\n",
"\n",
"for pr in assigned_pr:\n",
" tmp = {\n",
" \"title\": pr.title,\n",
" \"number\": pr.number,\n",
" \"url\": pr.html_url,\n",
" \"assignee\": pr.assignee.login,\n",
" \"created_at\": pr.created_at.isoformat(),\n",
" \"updated_at\": pr.updated_at.isoformat(),\n",
" \"merged_at\": pr.merged_at.isoformat(),\n",
" }\n",
" data.append(tmp)\n",
"df_pr = pd.DataFrame(data)\n",
"\n",
"# Set the display option for max column width to ensure the link is fully displayed\n",
"pd.set_option('display.max_colwidth', None)\n",
"if len(df_pr) > 0:\n",
" # Filter df_init with the URLs from df_pr\n",
" filtered_df_init = df_estimates[df_estimates[\"PR URL\"].isin(df_pr[\"url\"])]\n",
" filtered_df_init['Estimate'] = filtered_df_init['Estimate'].str.replace(\"null\", \"0\")\n",
"\n",
"# Convert the \"PR URL\" column values into clickable links using HTML formatting\n",
"filtered_df_init[\"PR URL\"] = filtered_df_init[\"PR URL\"].apply(lambda x: f'<a href=\"{x}\">{x}</a>')\n",
" # Set the display option for max column width to ensure the link is fully displayed\n",
" pd.set_option('display.max_colwidth', None)\n",
"\n",
"# Calculate the total of the \"Estimate\" column and convert it to an integer\n",
"total_estimate = int(filtered_df_init[\"Estimate\"].astype(float).sum())\n",
" # Convert the \"PR URL\" column values into clickable links using HTML formatting\n",
" filtered_df_init[\"PR URL\"] = filtered_df_init[\"PR URL\"].apply(lambda x: f'<a href=\"{x}\">{x}</a>')\n",
"\n",
"# Display the DataFrame with clickable links and format the \"Estimate\" column as integers\n",
"filtered_df_init[\"Estimate\"] = filtered_df_init[\"Estimate\"].astype(float).astype(int)\n",
"display(HTML(filtered_df_init.to_html(escape=False, index=False)))\n",
" # Calculate the total of the \"Estimate\" column and convert it to an integer\n",
" total_estimate = int(filtered_df_init[\"Estimate\"].astype(float).sum())\n",
"\n",
" # Display the DataFrame with clickable links and format the \"Estimate\" column as integers\n",
" filtered_df_init[\"Estimate\"] = filtered_df_init[\"Estimate\"].astype(float).astype(int)\n",
" filtered_df_init[\"Email_List\"] = filtered_df_init[\"Title\"] + \": \" + filtered_df_init[\"Estimate\"].astype(str)\n",
" display(HTML(filtered_df_init.to_html(escape=False, index=False)))\n",
"\n",
"# Separate sentence with emoji for the total estimate\n",
"print(f\"\\n🚀 The total estimate is: {total_estimate}\")"
Expand Down Expand Up @@ -425,30 +451,37 @@
"logo_img = \"https://landen.imgix.net/jtci2pxwjczr/assets/5ice39g4.png?w=186\"\n",
"\n",
"# Get the current date\n",
"current_date = datetime.now().strftime(\"%B %Y\")\n",
"\n",
"# Center-align the content of the email\n",
"center_style = 'style=\"text-align: center;\"'\n",
"scenario_display = scenario_filter.strftime(\"%B %Y\")\n",
"\n",
"# Convert the \"Estimate\" column values to string\n",
"filtered_df_init[\"Estimate\"] = filtered_df_init[\"Estimate\"].astype(str)\n",
"sum_estimates = 0\n",
"list_issues = []\n",
"if len(filtered_df_init) > 0:\n",
" sum_estimates = filtered_df_init[\"Estimate\"].astype(int).sum()\n",
" list_issues = [emailbuilder.link(row[\"PR URL\"], row[\"Email_List\"]) for index, row in filtered_df_init.iterrows()]\n",
"list_prs = [emailbuilder.link(pr.html_url, pr.title) for pr in reviewed_pr]\n",
"\n",
"reward_issues_merged = sum_estimates * 5\n",
"reward_prs_reviewed = len(list_prs) * 10\n",
"rewards = reward_issues_merged + reward_prs_reviewed\n",
"\n",
"# Define the content for the email using the email builder\n",
"email_content = {\n",
" \"element\": naas_drivers.emailbuilder.title(f'<div {center_style}>📝 Report on templates created for {contributor_profile}</div>'),\n",
" \"heading\": naas_drivers.emailbuilder.heading(f'<div {center_style}>Monthly Report - {current_date}</div>'),\n",
" \"text\": naas_drivers.emailbuilder.text(f'<div {center_style}>Here is the summary of your contributions for this month</div>'),\n",
" \"table\": naas_drivers.emailbuilder.table(filtered_df_init, header=True, border=True),\n",
" \"total_estimate\": naas_drivers.emailbuilder.text(f'<div {center_style}><b>Total Estimate: {total_estimate}</b></div>'),\n",
" \"footer\": naas_drivers.emailbuilder.footer_company(\n",
" networks=[{\"img_src\": logo_img, \"href\": \"\"}],\n",
" company=[\"Company Informations\"],\n",
" legal=[\"Legal Informations\"],\n",
" ),\n",
"# \"element\": naas_drivers.emailbuilder.title(f'<div {center_style}>📝 Report on templates created for {contributor_profile}</div>'),\n",
" \"heading\": emailbuilder.heading(f'Monthly Report - {scenario_display}'),\n",
" \"intro\": emailbuilder.text(f\"Hi {contributor_profile},\"),\n",
" \"reward\": emailbuilder.text(f'💵 Here is the reward your contribution as templates maintainer: {rewards}$'),\n",
" \"reward_det\": emailbuilder.list([f\"Issues closed by PRs merged: {reward_issues_merged} $\", f\"PRs reviewed: {reward_prs_reviewed} $\"]),\n",
" \"contrib\": emailbuilder.text(f'Please find below the detail of your contributions.'),\n",
" \"assign\": emailbuilder.text(f'🧑‍💻 Issues closed by PRs merged: {len(filtered_df_init)} (Total estimates: {sum_estimates})'),\n",
" \"assign_list\": emailbuilder.list(list_issues),\n",
" \"review\": emailbuilder.text(f'👀💻 PRs reviewed: {len(reviewed_pr)}'),\n",
" \"review_list\": emailbuilder.list(list_prs),\n",
" \"footer\": emailbuilder.footer_company(naas=True),\n",
"}\n",
"\n",
"# Generate the email content as HTML\n",
"content = naas_drivers.emailbuilder.generate(display=\"iframe\", **email_content)"
"content = emailbuilder.generate(display=\"iframe\", **email_content)"
]
},
{
Expand Down

0 comments on commit 9ceadbb

Please sign in to comment.