A lightweight data store using GitHub Issues as a backend
Project description
GitHub Issue Store
A lightweight data store using GitHub Issues as a backend. Store and update JSON objects using GitHub Issues as a persistent storage layer, with automatic update processing via GitHub Actions.
Features
- Store JSON objects in GitHub Issues
- Update objects through issue comments
- Automatic update processing via GitHub Actions
- Sequential update handling with atomic operations
- Full audit trail of all changes
- Idempotent processing with reaction-based tracking
- Configurable via YAML
- Type-safe Python interface
Installation
pip install gh-store
Or install from source:
git clone https://github.com/dmarx/gh-store.git
cd gh-store
pip install -e .
Quick Start
- Add the GitHub Actions workflow to your repository:
mkdir -p .github/workflows
cp gh_store/workflows/process_update.yml .github/workflows/
- Configure your GitHub token with repo access:
from gh_store import GitHubStore
store = GitHubStore(
token="your-github-token",
repo="owner/repository"
)
- Start using the store:
# Create an object
data = {"name": "test", "value": 42}
obj = store.create("my-object", data)
# Retrieve an object
obj = store.get("my-object")
# Update an object
store.update("my-object", {"value": 43})
How It Works
Object Storage
Each object is stored in a dedicated GitHub Issue:
- The issue body contains the current object state as JSON
- Each object has two labels:
stored-object: Base label for all stored objects- Custom label matching the object ID
- Issue state indicates processing status:
closed: Object is stableopen: Updates are being processed
Update Flow
- Updates are submitted as JSON comments on the object's issue
- The issue is reopened to trigger processing
- GitHub Actions runs the update processor
- Each comment is processed in chronological order
- Processed comments receive a "👍" reaction
- The issue is closed when all updates are processed
Example update flow:
# Initial state
obj = store.get("user-123")
print(obj.data)
# {"name": "Alice", "score": 10}
# Submit an update
store.update("user-123", {"score": 15})
# After processing
obj = store.get("user-123")
print(obj.data)
# {"name": "Alice", "score": 15}
Deep Updates
The store supports deep dictionary updates:
# Initial state
{
"user": {
"profile": {
"name": "Alice",
"settings": {"theme": "dark"}
},
"score": 10
}
}
# Update
store.update("user-123", {
"user": {
"profile": {
"settings": {"theme": "light"}
},
"score": 15
}
})
# Final state
{
"user": {
"profile": {
"name": "Alice",
"settings": {"theme": "light"}
},
"score": 15
}
}
Configuration
Create a config.yml file:
store:
base_label: "stored-object"
processed_reaction: "+1"
retries:
max_attempts: 3
backoff_factor: 2
rate_limit:
max_requests_per_hour: 1000
log:
level: "INFO"
format: "{time} | {level} | {message}"
Pass the config file path when initializing:
store = GitHubStore(
token="your-token",
repo="owner/repo",
config_path=Path("config.yml")
)
Error Handling
The store provides specific exceptions for common error cases:
from gh_store.core.exceptions import (
ObjectNotFound,
InvalidUpdate,
ConcurrentUpdateError
)
try:
obj = store.get("nonexistent")
except ObjectNotFound:
print("Object doesn't exist")
try:
store.update("user-123", "invalid json")
except InvalidUpdate:
print("Invalid update format")
Command Line Interface
The package includes a CLI for use in GitHub Actions:
# Process updates for an issue
python -m gh_store process-updates \
--issue 123 \
--token $GITHUB_TOKEN \
--repo "owner/repository"
Use Cases
The GitHub Issue Store is particularly useful for:
- Lightweight data storage without additional infrastructure
- Applications that need a full audit trail of changes
- Collaborative data management with GitHub-based workflows
- Prototypes and small projects
- Data that changes infrequently but needs version history
Limitations
- Not suitable for high-frequency updates
- GitHub API rate limits apply
- Maximum issue size limits apply
- Not recommended for sensitive data
- No transactional guarantees across multiple objects
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new features
- Submit a pull request
Testing
Run the test suite:
pytest
Run with coverage:
pytest --cov=gh_store
License
MIT License - see LICENSE file for details
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.2.0.tar.gz.
File metadata
- Download URL: gh_store-0.2.0.tar.gz
- Upload date:
- Size: 11.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.0.1 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43cbbdf9a06ae5a42e97af6ab2120fd608347625581ca9bdcff86b04a00c6539
|
|
| MD5 |
f70d0694050559253d78e370b0c050b8
|
|
| BLAKE2b-256 |
815563157065bd28fd9789460473c069e69be9a727c114af9187d38f1d8f305f
|
Provenance
The following attestation bundles were made for gh_store-0.2.0.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.2.0.tar.gz -
Subject digest:
43cbbdf9a06ae5a42e97af6ab2120fd608347625581ca9bdcff86b04a00c6539 - Sigstore transparency entry: 162830837
- Sigstore integration time:
-
Permalink:
dmarx/gh-store@1bb2da9d132cc23b631ca90739fae2a0b8b1cf57 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/dmarx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1bb2da9d132cc23b631ca90739fae2a0b8b1cf57 -
Trigger Event:
release
-
Statement type:
File details
Details for the file gh_store-0.2.0-py3-none-any.whl.
File metadata
- Download URL: gh_store-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.9 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 |
1f7cd7bd6d3cc494cac77aeefca2ab3e85276e3a73f59222633fc43ec79ace5b
|
|
| MD5 |
0b5cd0f6cd251461db7b2e93d6dca6b4
|
|
| BLAKE2b-256 |
33d365f0b43ae3a4e143b9195fb64746964329da897d11d864f0206954f21c8a
|
Provenance
The following attestation bundles were made for gh_store-0.2.0-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.2.0-py3-none-any.whl -
Subject digest:
1f7cd7bd6d3cc494cac77aeefca2ab3e85276e3a73f59222633fc43ec79ace5b - Sigstore transparency entry: 162830838
- Sigstore integration time:
-
Permalink:
dmarx/gh-store@1bb2da9d132cc23b631ca90739fae2a0b8b1cf57 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/dmarx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1bb2da9d132cc23b631ca90739fae2a0b8b1cf57 -
Trigger Event:
release
-
Statement type: