Compare commits

...

2 commits

Author SHA1 Message Date
2a37725b2e
feat: Option to serve Bootstrap from the filesystem
All checks were successful
/ pre-commit (push) Successful in 1m43s
Signed-off-by: Julien Riou <julien@riou.xyz>
2025-09-17 10:26:08 +02:00
5122000d48
feat: Create releases with make releases
All checks were successful
/ pre-commit (push) Successful in 1m9s
Fixes #22.

Signed-off-by: Julien Riou <julien@riou.xyz>
2025-09-17 10:24:35 +02:00
9 changed files with 162 additions and 19 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ releases
collerd.db collerd.db
!docker/collerd.json !docker/collerd.json
collerd.json collerd.json
node_modules

View file

@ -4,26 +4,64 @@ GITCOMMIT := $(shell git log -1 --oneline | awk '{print $$1}')
OS := $(shell uname -s | tr [A-Z] [a-z]) OS := $(shell uname -s | tr [A-Z] [a-z])
ARCH := $(shell uname -m | tr [A-Z] [a-z]) ARCH := $(shell uname -m | tr [A-Z] [a-z])
LDFLAGS = -X main.AppVersion=${APPVERSION} -X main.GoVersion=${GOVERSION} -X main.GitCommit=${GITCOMMIT} LDFLAGS = -X main.AppVersion=${APPVERSION} -X main.GoVersion=${GOVERSION} -X main.GitCommit=${GITCOMMIT}
DOCKER_IMAGE = golang:1.24-trixie
.PHONY: clean test .PHONY: clean clean_for_releases test
build: build:
(cd src \ cd src \
&& go build -ldflags "${LDFLAGS}" -o ../bin/collerd cmd/collerd/main.go \ && go build -ldflags "${LDFLAGS}" -o ../bin/collerd cmd/collerd/main.go \
&& go build -ldflags "${LDFLAGS}" -o ../bin/copier cmd/copier/main.go \ && go build -ldflags "${LDFLAGS}" -o ../bin/copier cmd/copier/main.go \
&& go build -ldflags "${LDFLAGS}" -o ../bin/coller cmd/coller/main.go \ && go build -ldflags "${LDFLAGS}" -o ../bin/coller cmd/coller/main.go
)
archive: build_linux_amd64:
(mkdir -p releases && cd bin && tar cvzpf ../releases/coller-${APPVERSION}-${OS}-${ARCH}.tar.gz * && cd ../releases && sha256sum *.tar.gz) cd src \
&& GOOS=linux GOARCH=amd64 go build -ldflags "${LDFLAGS}" -o ../bin/collerd-${APPVERSION}-linux-amd64 cmd/collerd/main.go \
&& GOOS=linux GOARCH=amd64 go build -ldflags "${LDFLAGS}" -o ../bin/coller-${APPVERSION}-linux-amd64 cmd/coller/main.go \
&& GOOS=linux GOARCH=amd64 go build -ldflags "${LDFLAGS}" -o ../bin/copier-${APPVERSION}-linux-amd64 cmd/copier/main.go
release: build archive archive_linux_amd64:
mkdir -p releases/coller-${APPVERSION}-linux-amd64 \
&& cp bin/collerd-${APPVERSION}-linux-amd64 releases/coller-${APPVERSION}-linux-amd64/collerd \
&& cp bin/coller-${APPVERSION}-linux-amd64 releases/coller-${APPVERSION}-linux-amd64/coller \
&& cp bin/copier-${APPVERSION}-linux-amd64 releases/coller-${APPVERSION}-linux-amd64/copier \
&& cd releases/ \
&& tar cvpzf coller-${APPVERSION}-linux-amd64.tar.gz coller-${APPVERSION}-linux-amd64
build_darwin_arm64:
cd src \
&& GOOS=darwin GOARCH=arm64 go build -ldflags "${LDFLAGS}" -o ../bin/collerd-${APPVERSION}-darwin-arm64 cmd/collerd/main.go \
&& GOOS=darwin GOARCH=arm64 go build -ldflags "${LDFLAGS}" -o ../bin/coller-${APPVERSION}-darwin-arm64 cmd/coller/main.go \
&& GOOS=darwin GOARCH=arm64 go build -ldflags "${LDFLAGS}" -o ../bin/copier-${APPVERSION}-darwin-arm64 cmd/copier/main.go
archive_darwin_arm64:
mkdir -p releases/coller-${APPVERSION}-darwin-arm64 \
&& cp bin/collerd-${APPVERSION}-darwin-arm64 releases/coller-${APPVERSION}-darwin-arm64/collerd \
&& cp bin/coller-${APPVERSION}-darwin-arm64 releases/coller-${APPVERSION}-darwin-arm64/coller \
&& cp bin/copier-${APPVERSION}-darwin-arm64 releases/coller-${APPVERSION}-darwin-arm64/copier \
&& cd releases/ \
&& tar cvpzf coller-${APPVERSION}-darwin-arm64.tar.gz coller-${APPVERSION}-darwin-arm64
checksum:
cd releases \
&& sha256sum *.tar.gz > checksums.txt
clean_for_releases:
rm -rf releases/coller-${APPVERSION}-linux-amd64 \
&& rm -rf releases/coller-${APPVERSION}-darwin-arm64
releases: build_linux_amd64 build_darwin_arm64 archive_linux_amd64 archive_darwin_arm64 checksum clean_for_releases
releases_with_docker:
docker run -it -v $(shell pwd):/mnt -w /mnt -e "UID=$(shell id -u)" -e "GID=$(shell id -g)" ${DOCKER_IMAGE} ./docker/build.sh
dependencies:
npm install
test: test:
(cd src \ cd src \
&& go test internal/*.go \ && go test internal/*.go \
&& go test server/*.go \ && go test server/*.go
)
clean: clean:
rm -rf bin releases rm -rf bin releases

20
docker/build.sh Executable file
View file

@ -0,0 +1,20 @@
#!/bin/bash
# Script to create releases with Docker
# Used by `make releases_with_docker`
set -e
if [ -z "UID" ] ; then
echo "UID not defined"
exit 1
fi
if [ -z "GID" ] ; then
echo "GID not defined"
exit 1
fi
apt-get update
apt-get install -y libx11-dev
make releases
chown ${UID}:${GID} -R releases

40
package-lock.json generated Normal file
View file

@ -0,0 +1,40 @@
{
"name": "coller",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"bootstrap": "^5.3.8"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/bootstrap": {
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
}
}
}

5
package.json Normal file
View file

@ -0,0 +1,5 @@
{
"dependencies": {
"bootstrap": "^5.3.8"
}
}

View file

@ -34,6 +34,7 @@ The file format is **JSON**:
* **languages** ([]string): List of supported [languages](https://github.com/microsoft/monaco-editor/tree/main/src/basic-languages) * **languages** ([]string): List of supported [languages](https://github.com/microsoft/monaco-editor/tree/main/src/basic-languages)
* **language** (string): Default language (default "text") * **language** (string): Default language (default "text")
* **enable_upload_file_button** (bool): Display the upload file button in the UI (default true) * **enable_upload_file_button** (bool): Display the upload file button in the UI (default true)
* **bootstrap_directory** (string): Serve [Bootstrap](https://getbootstrap.com/) assets from this local directory (ex: "./node_modules/bootstrap/dist"). See **Dependencies** for details.
The configuration file is not required but the service might not be exposed to the public. The configuration file is not required but the service might not be exposed to the public.
@ -76,4 +77,35 @@ If the note is encrypted, the encrypted value is returned (application/octet-str
Errors return **500 Server Internal Error** with the **JSON** payload: Errors return **500 Server Internal Error** with the **JSON** payload:
* **message** (string): context of the error * **message** (string): context of the error
* **error** (string): error message * **error** (string): error message
## Dependencies
The web interface depends on:
- [Bootstrap](https://getbootstrap.com/)
- [Monaco Editor](https://github.com/microsoft/monaco-editor/)
By default, those dependencies are fetched from **remote CDN** services by the client.
If you would like to download them to serve them locally:
```
npm install
```
or via `make`:
```
make dependencies
```
Then configure the local directories:
```json
{
"bootstrap_directory": "./node_modules/bootstrap/dist"
}
```
Downloading Monaco Editor is not supported yet.

View file

@ -26,6 +26,7 @@ type Config struct {
Languages []string `json:"languages"` Languages []string `json:"languages"`
Language string `json:"language"` Language string `json:"language"`
EnableUploadFileButton bool `json:"enable_upload_file_button"` EnableUploadFileButton bool `json:"enable_upload_file_button"`
BootstrapDirectory string `json:"bootstrap_directory"`
} }
func NewConfig() *Config { func NewConfig() *Config {

View file

@ -195,6 +195,7 @@ type PageData struct {
URL string URL string
Note *Note Note *Note
EnableUploadFileButton bool EnableUploadFileButton bool
BootstrapDirectory string
} }
type HomeHandler struct { type HomeHandler struct {
@ -429,10 +430,11 @@ func (s *Server) Start() error {
"string": func(b []byte) string { return string(b) }, "string": func(b []byte) string { return string(b) },
} }
p := PageData{ p := PageData{
Title: s.config.Title, Title: s.config.Title,
Expirations: s.config.Expirations, Expirations: s.config.Expirations,
Expiration: s.config.Expiration, Expiration: s.config.Expiration,
Languages: s.config.Languages, Languages: s.config.Languages,
BootstrapDirectory: s.config.BootstrapDirectory,
} }
if s.config.ShowVersion { if s.config.ShowVersion {
@ -469,6 +471,10 @@ func (s *Server) Start() error {
} }
r.Path("/{id:[a-zA-Z0-9]+}.html").Handler(webNoteHandler).Methods("GET") r.Path("/{id:[a-zA-Z0-9]+}.html").Handler(webNoteHandler).Methods("GET")
if s.config.BootstrapDirectory != "" {
r.PathPrefix("/static/bootstrap/").Handler(http.StripPrefix("/static/bootstrap/", http.FileServer(http.Dir(s.config.BootstrapDirectory))))
}
r.Path("/").Handler(&HomeHandler{Templates: templates, PageData: p}).Methods("GET") r.Path("/").Handler(&HomeHandler{Templates: templates, PageData: p}).Methods("GET")
addr := fmt.Sprintf("%s:%d", s.config.ListenAddress, s.config.ListenPort) addr := fmt.Sprintf("%s:%d", s.config.ListenAddress, s.config.ListenPort)

View file

@ -4,6 +4,6 @@
<title>{{.Title}}</title> <title>{{.Title}}</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="{{if ne .BootstrapDirectory ``}}/static/bootstrap/css/bootstrap.min.css{{else}}https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css{{end}}" rel="stylesheet">
</head> </head>
{{end}} {{end}}