+47
.dockerignore
+47
.dockerignore
···
1
+
# Git
2
+
.git
3
+
.gitignore
4
+
5
+
# Build artifacts
6
+
*.exe
7
+
*.exe~
8
+
*.dll
9
+
*.so
10
+
*.dylib
11
+
*.test
12
+
*.out
13
+
/bin/
14
+
/dist/
15
+
16
+
# Data directories
17
+
/data/
18
+
*.jsonl.zst
19
+
*.jsonl
20
+
*.json
21
+
plc_mempool_*
22
+
plc_bundles.json
23
+
24
+
# IDE
25
+
.vscode/
26
+
.idea/
27
+
*.swp
28
+
*.swo
29
+
*~
30
+
31
+
# OS
32
+
.DS_Store
33
+
Thumbs.db
34
+
35
+
# Docs
36
+
*.md
37
+
docs/
38
+
examples/
39
+
40
+
# CI/CD
41
+
.github/
42
+
.gitlab-ci.yml
43
+
44
+
# Docker
45
+
Dockerfile*
46
+
docker-compose*.yml
47
+
.dockerignore
+34
Dockerfile
+34
Dockerfile
···
1
+
# syntax=docker/dockerfile:1
2
+
3
+
FROM golang:1.25.3-alpine AS builder
4
+
5
+
RUN apk add --no-cache git gcc musl-dev zstd-dev
6
+
7
+
WORKDIR /build
8
+
9
+
COPY go.mod go.sum ./
10
+
RUN go mod download
11
+
12
+
COPY . .
13
+
14
+
RUN CGO_ENABLED=1 go build \
15
+
-ldflags="-w -s" \
16
+
-trimpath \
17
+
-o plcbundle \
18
+
./cmd/plcbundle
19
+
20
+
FROM alpine:3.19
21
+
22
+
RUN apk add --no-cache ca-certificates zstd-libs
23
+
24
+
RUN addgroup -g 1000 plcbundle && \
25
+
adduser -D -u 1000 -G plcbundle plcbundle && \
26
+
mkdir -p /data && \
27
+
chown plcbundle:plcbundle /data
28
+
29
+
COPY --from=builder /build/plcbundle /usr/local/bin/plcbundle
30
+
31
+
WORKDIR /data
32
+
USER plcbundle
33
+
34
+
ENTRYPOINT ["plcbundle"]
+76
-3
Makefile
+76
-3
Makefile
···
1
1
.PHONY: all build install test clean fmt lint help version bump-patch bump-minor bump-major release
2
+
.PHONY: docker-build docker-push docker-run docker-clean docker-shell compose-up compose-down compose-logs
2
3
3
4
# Binary name
4
5
BINARY_NAME=plcbundle
5
6
INSTALL_PATH=$(GOPATH)/bin
7
+
8
+
# Docker configuration
9
+
DOCKER_IMAGE=plcbundle
10
+
DOCKER_TAG=$(VERSION)
11
+
DOCKER_REGISTRY?=
12
+
DOCKER_FULL_IMAGE=$(if $(DOCKER_REGISTRY),$(DOCKER_REGISTRY)/,)$(DOCKER_IMAGE):$(DOCKER_TAG)
13
+
DOCKER_LATEST=$(if $(DOCKER_REGISTRY),$(DOCKER_REGISTRY)/,)$(DOCKER_IMAGE):latest
6
14
7
15
# Version information
8
16
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
···
93
101
@echo "Creating release for version $(VERSION)..."
94
102
@./scripts/release.sh
95
103
96
-
# Show help
104
+
# ============================================================================
105
+
# Docker Commands
106
+
# ============================================================================
107
+
108
+
# Build Docker image
109
+
docker-build:
110
+
@echo "Building Docker image $(DOCKER_FULL_IMAGE)..."
111
+
docker build \
112
+
--build-arg VERSION=$(VERSION) \
113
+
--build-arg GIT_COMMIT=$(GIT_COMMIT) \
114
+
-t $(DOCKER_FULL_IMAGE) \
115
+
-t $(DOCKER_LATEST) \
116
+
.
117
+
@echo "✓ Built: $(DOCKER_FULL_IMAGE)"
118
+
119
+
# Push Docker image to registry
120
+
docker-push:
121
+
@echo "Pushing Docker image..."
122
+
docker push $(DOCKER_FULL_IMAGE)
123
+
docker push $(DOCKER_LATEST)
124
+
@echo "✓ Pushed: $(DOCKER_FULL_IMAGE)"
125
+
126
+
# Build and push
127
+
docker-release: docker-build docker-push
128
+
129
+
# Run Docker container as CLI
130
+
docker-run:
131
+
docker run --rm -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) $(CMD)
132
+
133
+
# Run Docker container as server
134
+
docker-serve:
135
+
docker run --rm -it \
136
+
-p 8080:8080 \
137
+
-v $(PWD)/data:/data \
138
+
$(DOCKER_FULL_IMAGE) \
139
+
plcbundle serve --host 0.0.0.0
140
+
141
+
# Open shell in Docker container
142
+
docker-shell:
143
+
docker run --rm -it -v $(PWD)/data:/data $(DOCKER_FULL_IMAGE) sh
144
+
145
+
# Clean Docker artifacts
146
+
docker-clean:
147
+
@echo "Cleaning Docker images..."
148
+
docker rmi $(DOCKER_FULL_IMAGE) $(DOCKER_LATEST) 2>/dev/null || true
149
+
docker image prune -f
150
+
151
+
# ============================================================================
152
+
# Help
153
+
# ============================================================================
154
+
97
155
help:
98
156
@echo "Available targets:"
157
+
@echo ""
158
+
@echo "Build & Install:"
99
159
@echo " make build - Build the CLI tool"
100
160
@echo " make install - Install CLI tool globally"
161
+
@echo " make clean - Clean build artifacts"
162
+
@echo ""
163
+
@echo "Development:"
101
164
@echo " make test - Run tests"
102
165
@echo " make test-coverage - Run tests with coverage"
103
-
@echo " make clean - Clean build artifacts"
104
166
@echo " make fmt - Format code"
105
167
@echo " make deps - Download dependencies"
106
168
@echo " make verify - Verify dependencies"
169
+
@echo ""
170
+
@echo "Versioning:"
107
171
@echo " make version - Show current version"
108
172
@echo " make bump-patch - Bump patch version (0.1.0 -> 0.1.1)"
109
173
@echo " make bump-minor - Bump minor version (0.1.0 -> 0.2.0)"
110
174
@echo " make bump-major - Bump major version (0.1.0 -> 1.0.0)"
111
175
@echo " make release - Create and push release tag"
112
-
@echo " make help - Show this help"
176
+
@echo ""
177
+
@echo "Docker:"
178
+
@echo " make docker-build - Build Docker image"
179
+
@echo " make docker-push - Push image to registry"
180
+
@echo " make docker-release - Build and push"
181
+
@echo " make docker-run - Run as CLI (CMD='info')"
182
+
@echo " make docker-serve - Run as server"
183
+
@echo " make docker-shell - Open shell in container"
184
+
@echo " make docker-clean - Remove Docker images"
185
+
@echo ""
+62
-26
README.md
+62
-26
README.md
···
35
35
* 💻 [CLI Guide](./docs/cli.md)
36
36
* 📰 [Announcement Article](https://leaflet.pub/feb982b4-64cb-4549-9d25-d7e68cecb11a)
37
37
38
-
## What is `plcbundle`?
38
+
## What is plcbundle?
39
39
40
-
plcbundle solves the problem of synchronizing and archiving PLC directory operations by:
40
+
plcbundle is a **format specification** for archiving PLC directory operations:
41
41
42
42
- **Bundling**: Groups 10,000 operations into compressed, immutable files
43
43
- **Chaining**: Each bundle is cryptographically linked to the previous one
44
44
- **Verifiable**: SHA-256 hashes ensure data integrity throughout the chain
45
45
- **Efficient**: Zstandard compression with ~5x compression ratios
46
46
47
+
### Implementations
48
+
49
+
- **Go** (this repository) - Full-featured CLI tool, library, and HTTP server
50
+
- [TypeScript, Python, Ruby](https://tangled.org/@atscan.net/plcbundle-ref/) - Reference implementations
51
+
52
+
## This Implementation (Go)
53
+
54
+
This Go implementation provides:
55
+
56
+
- 📚 **Library** - Embed bundle operations in your Go applications
57
+
- 💻 **CLI Tool** - Command-line interface for all operations
58
+
- 🌐 **HTTP Server** - Host and serve bundles over HTTP
59
+
- 🔄 **Auto-sync** - Automatically fetch and bundle new operations
60
+
- 🔌 **WebSocket** - Stream operations in real-time
61
+
- 🔍 **Spam Detection** - Built-in and custom JavaScript detectors
62
+
- ⚡ **Performance** - Parallel processing, efficient compression
63
+
- 🐳 **Docker** - Ready-to-deploy containers
64
+
65
+
## Installation
66
+
67
+
### Go Install
68
+
69
+
```bash
70
+
# CLI tool
71
+
go install tangled.org/atscan.net/plcbundle/cmd/plcbundle@latest
72
+
73
+
# Library
74
+
go get tangled.org/atscan.net/plcbundle
75
+
```
76
+
77
+
### Docker
78
+
79
+
```bash
80
+
# Build
81
+
docker build -t plcbundle .
82
+
83
+
# Run CLI
84
+
docker run --rm -v $(pwd)/data:/data plcbundle info
85
+
docker run --rm -v $(pwd)/data:/data plcbundle fetch
86
+
87
+
# Run as server
88
+
docker-compose up -d
89
+
```
90
+
91
+
### From Source
92
+
93
+
```bash
94
+
git clone https://tangled.org/@atscan.net/plcbundle
95
+
cd plcbundle
96
+
make build
97
+
sudo make install
98
+
```
99
+
47
100
## Quick Start
48
101
49
102
### As a Library
···
63
116
### As a CLI Tool
64
117
65
118
```bash
66
-
# Install
67
-
go install tangled.org/atscan.net/plcbundle/cmd/plcbundle@latest
68
-
69
-
# Fetch bundles
119
+
# Fetch bundles from plc.directory
70
120
plcbundle fetch
71
121
72
122
# Clone from remote
···
78
128
79
129
[See full CLI reference →](./docs/cli.md)
80
130
81
-
## Key Features
82
-
83
-
- 📦 Automatic bundle management (10,000 operations each)
84
-
- 🔄 Transparent synchronization with PLC directory
85
-
- 🗜️ Efficient zstd compression
86
-
- ✅ Cryptographic verification (SHA-256 + chain validation)
87
-
- 🔍 Fast indexing and gap detection
88
-
- 🌐 HTTP server for hosting bundles
89
-
- 🔌 WebSocket streaming support
90
-
91
-
## Installation
131
+
### With Docker
92
132
93
133
```bash
94
-
# Library
95
-
go get tangled.org/atscan.net/plcbundle
134
+
# CLI usage
135
+
docker run --rm -v $(pwd)/data:/data plcbundle info
96
136
97
-
# CLI tool
98
-
go install tangled.org/atscan.net/plcbundle/cmd/plcbundle@latest
137
+
# Server mode
138
+
docker-compose up -d
139
+
curl http://localhost:8080/
99
140
```
100
141
101
142
## Use Cases
···
113
154
- ✅ Check published root and head hashes
114
155
- ✅ Anyone can reproduce bundles from PLC directory
115
156
116
-
## Reference Implementations
117
-
118
-
- [TypeScript, Python, Ruby](https://tangled.org/@atscan.net/plcbundle-ref/)
119
-
120
157
## Documentation
121
158
122
159
- [Library Guide](./docs/library.md) - Comprehensive API documentation
123
160
- [CLI Guide](./docs/cli.md) - Command-line tool usage
124
161
- [Specification](./docs/specification.md) - Technical format specification
125
-
<!--- [Examples](./docs/examples/) - Common patterns and recipes-->
126
162
127
163
## License
128
164
+51
docker-compose.yaml
+51
docker-compose.yaml
···
1
+
services:
2
+
plcbundle:
3
+
build: .
4
+
image: plcbundle:latest
5
+
container_name: plcbundle
6
+
restart: unless-stopped
7
+
8
+
ports:
9
+
- "${HTTP_PORT:-8080}:8080"
10
+
11
+
volumes:
12
+
- ${DATA_DIR:-./data}:/data
13
+
14
+
environment:
15
+
- TZ=${TZ:-UTC}
16
+
17
+
command: >
18
+
plcbundle serve
19
+
--host 0.0.0.0
20
+
--port 8080
21
+
--sync
22
+
--websocket
23
+
24
+
networks:
25
+
- plcbundle
26
+
27
+
networks:
28
+
plcbundle:
29
+
30
+
# Optional: Caddy reverse proxy
31
+
#
32
+
# services:
33
+
# caddy:
34
+
# image: caddy:2-alpine
35
+
# restart: unless-stopped
36
+
# ports:
37
+
# - "80:80"
38
+
# - "443:443"
39
+
# - "443:443/udp"
40
+
# volumes:
41
+
# - caddy_data:/data
42
+
# environment:
43
+
# - DOMAIN=${DOMAIN:-localhost}
44
+
# command: caddy reverse-proxy --from ${DOMAIN:-localhost} --to plcbundle:8080
45
+
# depends_on:
46
+
# - plcbundle
47
+
# networks:
48
+
# - plcbundle
49
+
#
50
+
# volumes:
51
+
# caddy_data: