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
reposcope - For GitHub Actions:
issueswrite 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:
- New update is added as a comment with JSON changes
- Issue is reopened to trigger processing
- 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d356067f9b0d7d0312fb153067a3bf4bee5e0bed62f51bf29f0dbf07ae08fb77
|
|
| MD5 |
c09385a176816f7e3f766d2a31cc3dbd
|
|
| BLAKE2b-256 |
ff28daf293f4e534142e61bfdd4ffe965b3632f1edab86f108707bd7d6833987
|
Provenance
The following attestation bundles were made for gh_store-0.4.2.tar.gz:
Publisher:
release.yml on dmarx/gh-store
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gh_store-0.4.2.tar.gz -
Subject digest:
d356067f9b0d7d0312fb153067a3bf4bee5e0bed62f51bf29f0dbf07ae08fb77 - Sigstore transparency entry: 163290940
- Sigstore integration time:
-
Permalink:
dmarx/gh-store@a0e58a806eae51c8c69248fd1692d4b12bd7292a -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/dmarx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a0e58a806eae51c8c69248fd1692d4b12bd7292a -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47236cdbacb701d622e9c534955621dddacc5379ba8fece776077a1fea93bb7c
|
|
| MD5 |
1ad679d77864e443358a5c498e5c74e1
|
|
| BLAKE2b-256 |
314199f19a17688bd402b180456e6e5c3df5fb466b305dd52d1fedab3f178fdd
|
Provenance
The following attestation bundles were made for gh_store-0.4.2-py3-none-any.whl:
Publisher:
release.yml on dmarx/gh-store
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gh_store-0.4.2-py3-none-any.whl -
Subject digest:
47236cdbacb701d622e9c534955621dddacc5379ba8fece776077a1fea93bb7c - Sigstore transparency entry: 163290941
- Sigstore integration time:
-
Permalink:
dmarx/gh-store@a0e58a806eae51c8c69248fd1692d4b12bd7292a -
Branch / Tag:
refs/tags/v0.4.2 - Owner: https://github.com/dmarx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a0e58a806eae51c8c69248fd1692d4b12bd7292a -
Trigger Event:
release
-
Statement type: