DEV Community

Cover image for Solved: Create a GitHub Repository automatically when a New Project starts in Notion
Darian Vance
Darian Vance

Posted on • Originally published at wp.me

Solved: Create a GitHub Repository automatically when a New Project starts in Notion

🚀 Executive Summary

TL;DR: This guide provides a solution to automatically create GitHub repositories when new projects are initiated in Notion, eliminating manual overhead and ensuring consistent project setup. It details a Python-based automation workflow that monitors a Notion project database, provisions GitHub repos, and updates Notion entries with the new repository URLs.

🎯 Key Takeaways

  • The automation requires a Notion Integration Token with ‘Read content’, ‘Update content’, and ‘Insert content’ capabilities, and a GitHub Personal Access Token (PAT) with ‘repo’ scope.
  • A Python script utilizes the Notion API to query for projects with a ‘New’ status and the GitHub API to create repositories, then updates the Notion page status and adds the repository URL.
  • The script leverages environment variables loaded from a ‘config.env’ file for sensitive credentials and can be scheduled using ‘cron’ on Linux or Task Scheduler on Windows for periodic execution.
  • Common pitfalls include authentication errors (401/403) due to incorrect tokens or insufficient permissions, and GitHub repository naming conflicts (422) if a repo with the same name already exists.

Create a GitHub Repository automatically when a New Project starts in Notion

Introduction

In the fast-paced world of software development and project management, efficiency is paramount. Manual tasks, such as creating a new GitHub repository every time a project kicks off, are not only tedious but also prone to human error. This repetitive work detracts from valuable engineering time and can lead to inconsistencies in your project setup. The solution lies in automation – integrating your project management tool with your version control system.

This tutorial will guide you through building a robust, automated workflow that monitors your Notion project database. When a new project is initiated and marked with a specific status, our system will spring into action, automatically provisioning a new GitHub repository, naming it according to your project, and even updating the Notion entry with the new repository’s URL. Say goodbye to manual overhead and hello to seamless project initiation!

Prerequisites

To follow along with this tutorial, you will need the following:

  • A GitHub Account: To host your repositories.
  • A GitHub Personal Access Token (PAT): With repo scope to allow our script to create repositories.
  • A Notion Account: To manage your projects.
  • A Notion Integration Token: To allow our script to interact with your Notion workspace.
  • A Notion Database ID: The specific database where your projects are tracked.
  • Python 3.x: Our automation script will be written in Python.
  • The Python requests library: For making HTTP requests to Notion and GitHub APIs. You can install it using pip install requests.

Step-by-Step Guide

Step 1: Set up Notion Integration and Database

First, we need to prepare your Notion workspace to communicate with our automation script.

  1. Create a Notion Integration:
    • Go to My integrations.
    • Click “New integration”.
    • Give it a descriptive name (e.g., “GitHub Repo Creator”).
    • Select the workspace it belongs to.
    • For “Capabilities”, ensure “Read content”, “Update content”, and “Insert content” are checked.
    • Click “Submit”.
    • Copy the “Internal Integration Token”. This is your NOTION_TOKEN.
  2. Create a Project Database in Notion:
    • In your Notion workspace, create a new database (e.g., “Projects”).
    • Add the following properties:
      • Name (Title type): For the project name.
      • Status (Select type): Add options like “New”, “Pending Repo”, “Repo Created”, “In Progress”, “Completed”. We will use “New” as our trigger and “Repo Created” as the success state.
      • GitHub Repo URL (URL type): This will store the link to the newly created GitHub repository.
    • Share the Database with your Integration:
      • Open your newly created “Projects” database page.
      • Click the “Share” button at the top right.
      • Click “Invite”, find your integration by its name (e.g., “GitHub Repo Creator”), and grant it “Can edit” access.
    • Get the Database ID:
      • The Database ID is part of the URL when you view the database in Notion. It’s the string of 32 characters between your workspace name and the ‘?’ or ‘#’. For example, in https://www.notion.so/[YOUR_WORKSPACE]/[DATABASE_ID]?v=..., copy the [DATABASE_ID]. This is your NOTION_DATABASE_ID.

Step 2: Generate GitHub Personal Access Token (PAT)

Our script needs authorization to create repositories on your behalf.

  1. Go to your GitHub profile settings (click your profile picture > Settings).
  2. In the left sidebar, navigate to “Developer settings” > “Personal access tokens” > “Tokens (classic)”.
  3. Click “Generate new token” and then “Generate new token (classic)”.
  4. Give the token a descriptive name (e.g., “Notion Automation”).
  5. Set an expiration date if desired (or “No expiration” for simplicity in testing, but be cautious in production).
  6. Under “Select scopes”, check the box next to repo (this grants full control of private repositories, necessary for creation).
  7. Click “Generate token”.
  8. CRITICAL: Copy the generated token immediately. GitHub will not show it again. This is your GITHUB_TOKEN. Treat it like a password.

Step 3: Develop the Python Script for Automation

Now, let’s write the Python script that connects Notion and GitHub.

First, create a file named config.env to store your sensitive credentials. Remember to replace the placeholders.

# config.env
NOTION_TOKEN='secret_YOUR_NOTION_INTEGRATION_TOKEN_HERE'
NOTION_DATABASE_ID='YOUR_NOTION_DATABASE_ID_HERE'
GITHUB_TOKEN='ghp_YOUR_GITHUB_PERSONAL_ACCESS_TOKEN_HERE'
GITHUB_USERNAME='YOUR_GITHUB_USERNAME_HERE'
Enter fullscreen mode Exit fullscreen mode

Next, create the Python script named notion_github_automation.py. This script will:

  1. Load environment variables from config.env.
  2. Query the Notion database for pages with a “New” status.
  3. For each “New” project:
    • Extract the project name.
    • Call the GitHub API to create a new repository with that name.
    • Update the Notion page’s status to “Repo Created” and add the GitHub repository URL.
import os
import requests
from dotenv import load_dotenv

# Load environment variables from config.env
load_dotenv(dotenv_path='config.env')

NOTION_TOKEN = os.getenv('NOTION_TOKEN')
NOTION_DATABASE_ID = os.getenv('NOTION_DATABASE_ID')
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
GITHUB_USERNAME = os.getenv('GITHUB_USERNAME')

NOTION_API_URL = "https://api.notion.com/v1"
GITHUB_API_URL = "https://api.github.com"

# Notion Headers
notion_headers = {
    "Authorization": f"Bearer {NOTION_TOKEN}",
    "Content-Type": "application/json",
    "Notion-Version": "2022-06-28"
}

# GitHub Headers
github_headers = {
    "Authorization": f"token {GITHUB_TOKEN}",
    "Accept": "application/vnd.github.v3+json",
    "X-GitHub-Api-Version": "2022-11-28"
}

def get_new_projects():
    """Fetches projects from Notion with 'New' status."""
    filter_payload = {
        "filter": {
            "property": "Status",
            "select": {
                "equals": "New"
            }
        }
    }
    response = requests.post(
        f"{NOTION_API_URL}/databases/{NOTION_DATABASE_ID}/query",
        headers=notion_headers,
        json=filter_payload
    )
    response.raise_for_status()
    return response.json().get('results', [])

def create_github_repo(repo_name):
    """Creates a new GitHub repository."""
    repo_data = {
        "name": repo_name,
        "description": f"Repository for Notion project: {repo_name}",
        "private": False # Set to True for private repos
    }
    response = requests.post(
        f"{GITHUB_API_URL}/user/repos", # Or /orgs/YOUR_ORG/repos for organization repos
        headers=github_headers,
        json=repo_data
    )
    response.raise_for_status()
    return response.json().get('html_url')

def update_notion_page(page_id, repo_url):
    """Updates a Notion page with the new status and repo URL."""
    update_payload = {
        "properties": {
            "Status": {
                "select": {
                    "name": "Repo Created"
                }
            },
            "GitHub Repo URL": {
                "url": repo_url
            }
        }
    }
    response = requests.patch(
        f"{NOTION_API_URL}/pages/{page_id}",
        headers=notion_headers,
        json=update_payload
    )
    response.raise_for_status()
    print(f"Notion page {page_id} updated with repo URL: {repo_url}")

def main():
    print("Checking Notion for new projects...")
    new_projects = get_new_projects()

    if not new_projects:
        print("No new projects found with 'New' status.")
        return

    for project in new_projects:
        page_id = project['id']
        project_name = project['properties']['Name']['title'][0]['plain_text']

        print(f"Found new project: {project_name} (Page ID: {page_id})")

        try:
            repo_url = create_github_repo(project_name)
            print(f"Successfully created GitHub repo: {repo_url}")
            update_notion_page(page_id, repo_url)
            print(f"Notion page for {project_name} updated.")
        except requests.exceptions.HTTPError as e:
            print(f"Error processing project {project_name}: {e}")
            print(f"Response content: {e.response.text}")
        except IndexError:
            print(f"Error: Project name not found for page ID {page_id}. Skipping.")
        except Exception as e:
            print(f"An unexpected error occurred for project {project_name}: {e}")

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

To run the script, ensure you have the python-dotenv library installed (pip install python-dotenv), then execute:

python3 notion_github_automation.py
Enter fullscreen mode Exit fullscreen mode

Step 4: Schedule the Automation

To make this truly automatic, you’ll want to schedule the Python script to run periodically.

On Linux systems, cron is the standard tool. You can open your crontab for editing:

crontab -e
Enter fullscreen mode Exit fullscreen mode

Then add a line like the following to run the script every 15 minutes (adjust the path to your script and Python executable):

*/15 * * * * python3 /path/to/your/notion_github_automation.py >> /home/user/logs/notion_github_automation.log 2>error.log
Enter fullscreen mode Exit fullscreen mode

For Windows, you can use Task Scheduler. For cloud environments, consider serverless functions (AWS Lambda, Azure Functions, Google Cloud Functions) triggered by a schedule, or containerized solutions orchestrated by Kubernetes or ECS.

Common Pitfalls

  • Authentication Errors (401/403 HTTP Codes):
    • Notion: Double-check your NOTION_TOKEN in config.env. Ensure the Notion integration has been invited to the specific database page and granted “Can edit” access.
    • GitHub: Verify your GITHUB_TOKEN and ensure it has the necessary repo scope. PATs can expire, so check its validity.
  • Notion Database ID/Property Name Issues (400 HTTP Code):
    • Ensure NOTION_DATABASE_ID is correct.
    • Verify that the property names used in the script (e.g., “Status”, “Name”, “GitHub Repo URL”) exactly match those in your Notion database, including capitalization and spaces.
  • GitHub Repository Naming Conflicts (422 HTTP Code):
    • If you try to create a repository with a name that already exists under your GitHub account or organization, GitHub will return an error. Implement logic in your script to handle this, perhaps by appending a timestamp or unique ID, or checking for existing repos first.

Conclusion

By following this tutorial, you’ve successfully automated the tedious process of creating GitHub repositories directly from your Notion project management database. This integration not only saves time and reduces manual errors but also ensures consistency across your project setups, allowing your team to focus on what truly matters: building great products.

This is just the beginning! You could expand this automation further by:

  • Adding more sophisticated error handling and notification mechanisms (e.g., Slack or email alerts).
  • Incorporating GitHub webhooks for real-time Notion updates instead of polling.
  • Automating other aspects of project setup, such as creating initial README files, setting up branch protection rules, or integrating with CI/CD pipelines.
  • Using a more robust secrets management solution for production environments instead of config.env.

Embrace automation, streamline your workflows, and empower your DevOps journey with TechResolve!


Darian Vance

👉 Read the original article on TechResolve.blog


Support my work

If this article helped you, you can buy me a coffee:

👉 https://buymeacoffee.com/darianvance

Top comments (0)