Skip to main content

A lightweight data store using GitHub Issues as a backend

Project description

gh-store

A data store implementation using GitHub Issues as a backend. Provides versioned storage and update capabilities for applications running in GitHub's ecosystem.

Key Features

  • Store and version JSON objects using GitHub Issues
  • Atomic updates through a comment-based event system
  • Point-in-time snapshots for static site generation
  • Built-in GitHub Actions integration

Installation

pip install gh-store  # Requires Python 3.12+

Prerequisites

  • GitHub repository with Issues enabled
  • GitHub token with repo scope
  • For GitHub Actions: issues write permission

Basic Usage

from gh_store.core.store import GitHubStore

store = GitHubStore(
    token="github-token",
    repo="username/repository"
)

# Create object
store.create("metrics", {
    "count": 0,
    "last_updated": "2025-01-16T00:00:00Z"
})

# Update object
store.update("metrics", {"count": 1})

# Get current state
obj = store.get("metrics")
print(f"Current count: {obj.data['count']}")

System Architecture

gh-store uses GitHub Issues as a versioned data store. Here's how the components work together:

1. Object Storage Model

Each stored object is represented by a GitHub Issue:

Issue #123
├── Labels: ["stored-object", "UID:metrics"]
├── Body: Current object state (JSON)
└── Comments: Update history
    ├── Comment 1: Update {"count": 1}
    ├── Comment 2: Update {"field": "value"}
    └── Each comment includes the 👍 reaction when processed

Key components:

  • Base Label ("stored-object"): Identifies issues managed by gh-store
  • UID Label ("UID:{object-id}"): Uniquely identifies each stored object
  • Issue Body: Contains the current state as JSON
  • Comments: Store update history
  • Reactions: Track processed updates (👍)

2. Update Process

When updating an object:

  1. New update is added as a comment with JSON changes
  2. Issue is reopened to trigger processing
  3. GitHub Actions workflow processes updates:
    • Gets all unprocessed comments (no 👍 reaction)
    • Applies updates in chronological order
    • Adds 👍 reaction to mark comments as processed
    • Updates issue body with new state
    • Closes issue when complete

3. Core Components

  • GitHubStore: Main interface for CRUD operations
  • IssueHandler: Manages GitHub Issue operations
  • CommentHandler: Processes update comments

GitHub Actions Integration

Process Updates

# .github/workflows/process_update.yml
name: Process Updates

on:
  issues:
    types: [reopened]

jobs:
  process:
    runs-on: ubuntu-latest
    if: contains(github.event.issue.labels.*.name, 'stored-object')
    permissions:
      issues: write
    steps:
      - uses: actions/checkout@v4
      - name: Process Updates
        run: |
          gh-store process-updates \
            --issue ${{ github.event.issue.number }} \
            --token ${{ secrets.GITHUB_TOKEN }} \
            --repo ${{ github.repository }}

Create Snapshots

# .github/workflows/snapshot.yml
name: Snapshot

on:
  schedule:
    - cron: '0 0 * * *'  # Daily
  workflow_dispatch:

jobs:
  snapshot:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - name: Create Snapshot
        run: |
          gh-store snapshot \
            --token ${{ secrets.GITHUB_TOKEN }} \
            --repo ${{ github.repository }} \
            --output data/store-snapshot.json

CLI Commands

# Process updates for an issue
gh-store process-updates \
  --issue <issue-number> \
  --token <github-token> \
  --repo <owner/repo>

# Create snapshot
gh-store snapshot \
  --token <github-token> \
  --repo <owner/repo> \
  --output <path>

# Update existing snapshot
gh-store update-snapshot \
  --token <github-token> \
  --repo <owner/repo> \
  --snapshot-path <path>

Configuration

Create config.yml:

store:
  # Label identifying store issues
  base_label: "stored-object"
  
  # Prefix for object ID labels
  uid_prefix: "UID:"
  
  # Reaction marking processed comments
  processed_reaction: "+1"
  
  # API retry settings
  retries:
    max_attempts: 3
    backoff_factor: 2
    
  # Rate limiting
  rate_limit:
    max_requests_per_hour: 1000
    
  # Logging
  log:
    level: "INFO"
    format: "{time} | {level} | {message}"

Limitations

  • Not suitable for high-frequency updates (GitHub API limits)
  • Objects limited to Issue size (~65KB)
  • Updates processed asynchronously via GitHub Actions
  • Consider data visibility in public repositories

Development

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Type checking & linting
mypy .
ruff check .

License

MIT License - see LICENSE

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gh_store-0.4.2.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gh_store-0.4.2-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file gh_store-0.4.2.tar.gz.

File metadata

  • Download URL: gh_store-0.4.2.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.0.1 CPython/3.12.8

File hashes

Hashes for gh_store-0.4.2.tar.gz
Algorithm Hash digest
SHA256 d356067f9b0d7d0312fb153067a3bf4bee5e0bed62f51bf29f0dbf07ae08fb77
MD5 c09385a176816f7e3f766d2a31cc3dbd
BLAKE2b-256 ff28daf293f4e534142e61bfdd4ffe965b3632f1edab86f108707bd7d6833987

See more details on using hashes here.

Provenance

The following attestation bundles were made for gh_store-0.4.2.tar.gz:

Publisher: release.yml on dmarx/gh-store

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gh_store-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: gh_store-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 13.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.0.1 CPython/3.12.8

File hashes

Hashes for gh_store-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 47236cdbacb701d622e9c534955621dddacc5379ba8fece776077a1fea93bb7c
MD5 1ad679d77864e443358a5c498e5c74e1
BLAKE2b-256 314199f19a17688bd402b180456e6e5c3df5fb466b305dd52d1fedab3f178fdd

See more details on using hashes here.

Provenance

The following attestation bundles were made for gh_store-0.4.2-py3-none-any.whl:

Publisher: release.yml on dmarx/gh-store

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page