diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md
new file mode 100755
index 0000000..c989a89
--- /dev/null
+++ b/.chglog/CHANGELOG.tpl.md
@@ -0,0 +1,22 @@
+{{ range .Versions }}
+
+## {{ if .Tag.Previous }}[{{ .Tag.Name }}]({{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}){{ else }}{{ .Tag.Name }}{{ end }} ({{ datetime "2006-01-02" .Tag.Date }})
+
+{{ range .CommitGroups -}}
+### {{ .Title }}
+
+{{ range .Commits -}}
+* {{ .Subject }}
+{{ end }}
+{{ end -}}
+
+{{- if .NoteGroups -}}
+{{ range .NoteGroups -}}
+### {{ .Title }}
+
+{{ range .Notes }}
+{{ .Body }}
+{{ end }}
+{{ end -}}
+{{ end -}}
+{{ end -}}
diff --git a/.chglog/config.yml b/.chglog/config.yml
new file mode 100755
index 0000000..2c69658
--- /dev/null
+++ b/.chglog/config.yml
@@ -0,0 +1,37 @@
+---
+style: Github
+template: CHANGELOG.tpl.md
+info:
+ title: CHANGELOG
+ repository_url: https://git.mills.io/prologic/tube
+options:
+ commits:
+ filters:
+ Type:
+ - Add
+ - Fix
+ - Update
+ - Document
+ commit_groups:
+ title_maps:
+ Add: Features
+ Update: Updates
+ Fix: Bug Fixes
+ Document: Documentation
+ header:
+ pattern: "^((\\w+)\\s.*)$"
+ pattern_maps:
+ - Subject
+ - Type
+ refs:
+ actions:
+ - Closes
+ - Fixes
+ reverts:
+ pattern: "^Revert \"([\\s\\S]*)\"$"
+ pattern_maps:
+ - Header
+ notes:
+ keywords:
+ - NOTE
+ - BREAKING CHANGE
diff --git a/.dockerfiles/config.json b/.dockerfiles/config.json
new file mode 100644
index 0000000..b0bc86c
--- /dev/null
+++ b/.dockerfiles/config.json
@@ -0,0 +1,36 @@
+{
+ "library": [
+ {
+ "path": "/data/videos",
+ "prefix": ""
+ }
+ ],
+ "server": {
+ "host": "0.0.0.0",
+ "port": 8000,
+ "store_path": "/data/tube.db",
+ "upload_path": "/data/uploads",
+ "max_upload_size": 104857600
+ },
+ "thumbnailer": {
+ "timeout": 60
+ },
+ "transcoder": {
+ "timeout": 300,
+ "sizes": null
+ },
+ "feed": {
+ "external_url": "",
+ "title": "Feed Title",
+ "link": "http://your-url.example/about",
+ "description": "Feed Description",
+ "author": {
+ "name": "Author Name",
+ "email": "author@somewhere.example"
+ },
+ "copyright": "Copyright Text"
+ },
+ "copyright": {
+ "content": "All Content herein Public Domain and User Contributed."
+ }
+}
diff --git a/.dockerfiles/entrypoint.sh b/.dockerfiles/entrypoint.sh
new file mode 100755
index 0000000..872d4fd
--- /dev/null
+++ b/.dockerfiles/entrypoint.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+[ -n "${PUID}" ] && usermod -u "${PUID}" tube
+[ -n "${PGID}" ] && groupmod -g "${PGID}" tube
+
+printf "Configuring tube ..."
+[ -z "${DATA}" ] && DATA="/data"
+
+export DATA
+
+printf "Switching UID=%s and GID=%s\n" "${PUID}" "${PGID}"
+exec su-exec tube:ytube "$@"
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 0e54a2f..03cde8c 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -1,8 +1,18 @@
---
builds:
- -
- flags: -tags "static_build"
- ldflags: -w -X git.mills.io/prologic/tube/.Version={{.Version}} -X git.mills.io/prologic/tube/.Commit={{.Commit}}
+ - id: tube
+ binary: tube
+ main: .
+ flags:
+ - -installsuffix=netgo
+ tags:
+ - embed
+ - netcgo
+ - static_build
+ ldflags: >-
+ -w
+ -X git.mills.io/prologic/tube.Version={{.Version}}
+ -X git.mills.io/prologic/tube.Commit={{.Commit}}
env:
- CGO_ENABLED=0
goos:
@@ -12,57 +22,39 @@ builds:
- linux
goarch:
- amd64
- - arm
- arm64
-brews:
- -
- github:
- owner: prologic
- name: homebrew-tube
- homepage: "https://github.io/prologic/tube"
- description: |
- tube is a Youtube-like (without censorship and features you don't need!)
- Video Sharing App written in Go which also supports automatic
- transcoding to MP4 H.265 AAC, multiple collections and RSS feed.
- dependencies:
- - ffmpeg
- plist: |
-
-
-
-
- LabelTube
- ProgramArguments
-
- /usr/local/bin/tube
- /usr/local/etc/tube/config.json
-
- WorkingDirectory
- /usr/local
- StandardOutPath/usr/local/log/tube.log
- RunAtLoad
- KeepAlive
- Disabled
-
-
+
+dockers:
+ - image_templates: ["prologic/tube:{{ .Version }}-amd64"]
+ use: buildx
+ dockerfile: Dockerfile.goreleaser
+ build_flag_templates:
+ - "--platform=linux/amd64"
+ extra_files:
+ - ".dockerfiles/entrypoint.sh"
+ - ".dockerfiles/config.json"
+ - image_templates: ["prologic/tube:{{ .Version }}-arm64v8"]
+ use: buildx
+ goarch: arm64
+ dockerfile: Dockerfile.goreleaser
+ build_flag_templates:
+ - "--platform=linux/arm64/v8"
+ extra_files:
+ - ".dockerfiles/entrypoint.sh"
+ - ".dockerfiles/config.json"
+
+docker_manifests:
+ - name_template: prologic/tube:{{ .Version }}
+ image_templates:
+ - prologic/tube:{{ .Version }}-amd64
+ - prologic/tube:{{ .Version }}-arm64v8
+
signs:
- -
- artifacts: checksum
-archives:
- -
- replacements:
- darwin: Darwin
- linux: Linux
- windows: Windows
- 386: i386
- amd64: x86_64
-checksum:
- name_template: 'checksums.txt'
-snapshot:
- name_template: "{{ .Tag }}-next"
-changelog:
- sort: asc
- filters:
- exclude:
- - '^docs:'
- - '^test:'
+ - artifacts: checksum
+release:
+ gitea:
+ owner: prologic
+ name: tube
+ draft: false
+gitea_urls:
+ api: https://git.mills.io/api/v1/
diff --git a/Dockerfile b/Dockerfile
index 1257ed1..2049e14 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,14 +1,70 @@
# Build
-FROM prologic/go-builder:latest AS build
+FROM golang:alpine AS build
+
+RUN apk add --no-cache -U build-base git make ffmpeg-dev
+
+RUN mkdir -p /src
+
+WORKDIR /src
+
+# Copy Makefile
+COPY Makefile ./
+
+# Install deps
+RUN make deps
+
+# Copy go.mod and go.sum and install and cache dependencies
+COPY go.mod .
+COPY go.sum .
+
+# Copy static assets
+COPY ./static/* ./static/
+
+# Copy templates
+
+COPY ./templates/* ./templates/
+
+# Copy sources
+COPY *.go ./
+COPY ./app/*.go ./app/
+COPY ./importers/*.go ./importers/
+COPY ./media/*.go ./media/
+COPY ./utils/*.go ./utils/
+
+# Version/Commit (there there is no .git in Docker build context)
+# NOTE: This is fairly low down in the Dockerfile instructions so
+# we don't break the Docker build cache just be changing
+# unrelated files that actually haven't changed but caused the
+# COMMIT value to change.
+ARG VERSION="0.0.0"
+ARG COMMIT="HEAD"
+
+# Build server binary
+RUN make server VERSION=$VERSION COMMIT=$COMMIT
# Runtime
-FROM golang:alpine
+FROM alpine:latest
-RUN apk --no-cache -U add git build-base ffmpeg ffmpeg-dev
+RUN apk --no-cache -U add su-exec shadow ca-certificates tzdata ffmpeg
-RUN go install github.com/mutschler/mt@latest
+ENV PUID=1000
+ENV PGID=1000
-COPY --from=build /src/tube /tube
+RUN addgroup -g "${PGID}" tube && \
+ adduser -D -H -G tube -h /var/empty -u "${PUID}" tube && \
+ mkdir -p /data && chown -R tube:tube /data
-ENTRYPOINT ["/tube"]
-CMD [""]
+VOLUME /data
+
+WORKDIR /
+
+# force cgo resolver
+ENV GODEBUG=netdns=cgo
+
+COPY --from=build /src/tube /usr/local/bin/tube
+
+COPY .dockerfiles/entrypoint.sh /init
+COPY .dockerfiles/config.json /
+
+ENTRYPOINT ["/init"]
+CMD ["tube"]
diff --git a/Dockerfile.goreleaser b/Dockerfile.goreleaser
new file mode 100644
index 0000000..ec6b312
--- /dev/null
+++ b/Dockerfile.goreleaser
@@ -0,0 +1,26 @@
+# Runtime
+FROM alpine:latest
+
+RUN apk --no-cache -U add su-exec shadow ca-certificates tzdata ffmpeg
+
+ENV PUID=1000
+ENV PGID=1000
+
+RUN addgroup -g "${PGID}" tube && \
+ adduser -D -H -G tube -h /var/empty -u "${PUID}" tube && \
+ mkdir -p /data && chown -R tube:tube /data
+
+VOLUME /data
+
+WORKDIR /
+
+# force cgo resolver
+ENV GODEBUG=netdns=cgo
+
+COPY tube /usr/local/bin
+
+COPY .dockerfiles/entrypoint.sh /init
+COPY .dockerfiles/config.json /
+
+ENTRYPOINT ["/init"]
+CMD ["tube"]
diff --git a/Makefile b/Makefile
index 5836337..3a501dd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,38 +1,81 @@
-.PHONY: dev setup build install image test release clean
+-include environ.inc
+.PHONY: help deps dev build install image release test clean clean-all
-CGO_ENABLED=0
-VERSION=$(shell git describe --abbrev=0 --tags)
-COMMIT=$(shell git rev-parse --short HEAD)
+export CGO_ENABLED=0
+VERSION=$(shell git describe --abbrev=0 --tags 2>/dev/null || echo "0.0.0")
+COMMIT=$(shell git rev-parse --short HEAD || echo "HEAD")
+BRANCH=$(shell git rev-parse --abbrev-ref HEAD)
+GOCMD=go
+GOVER=$(shell go version | grep -o -E 'go1\.17\.[0-9]+')
-all: dev
+DESTDIR=/usr/local/bin
-dev: build
- @./tube -v
+ifeq ($(BRANCH), master)
+IMAGE := prologic/tube
+TAG := latest
+else
+IMAGE := prologic/tube
+TAG := dev
+endif
-setup:
- @go get github.com/GeertJohan/go.rice/rice
+all: help
-build: clean
- @command -v rice > /dev/null || make setup
- @go generate $(shell go list)/...
- @go build \
- -tags "netgo static_build" -installsuffix netgo \
- -ldflags "-w -X main.Version=$(VERSION) -X main.Commit=$(COMMIT)" \
+.PHONY: help
+
+help: ## Show this help message
+ @echo "tube - a Youtube-like (without censorship and features you don't need!) Video Sharing App"
+ @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[$$()% a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
+
+preflight: ## Run preflight checks to ensure you have the right build tools
+ @./preflight.sh
+
+deps: ## Install any dependencies required
+
+dev : DEBUG=1
+dev : server ## Build debug version of tube
+ @./tube
+
+server: generate ## Build the tube server
+ @$(GOCMD) build -tags "embed netgo static_build" -installsuffix netgo \
+ -ldflags "-w \
+ -X $(shell go list).Version=$(VERSION) \
+ -X $(shell go list).Commit=$(COMMIT)" \
.
-install: build
- @go install
+build: server ## Build the server
-docker-image:
- @docker build -t prologic/tube .
-docker-run:
- @docker run -p 8000:8000 -t prologic/tube .
+generate: ## Genereate any code required by the build
+ @if [ x"$(DEBUG)" = x"1" ]; then \
+ echo 'Running in debug mode...'; \
+ fi
-test: install
- @go test
+install: build ## Install tube to $DESTDIR
+ @install -D -m 755 tube $(DESTDIR)/tube
-release:
+ifeq ($(PUBLISH), 1)
+image: generate ## Build the Docker image
+ @docker build --build-arg VERSION="$(VERSION)" --build-arg COMMIT="$(COMMIT)" -t $(IMAGE):$(TAG) .
+ @docker push $(IMAGE):$(TAG)
+else
+image: generate
+ @docker build --build-arg VERSION="$(VERSION)" --build-arg COMMIT="$(COMMIT)" -t $(IMAGE):$(TAG) .
+endif
+
+release: generate ## Release a new version to Gitea
@./tools/release.sh
-clean:
+fmt: ## Format sources fiels
+ @$(GOCMD) fmt ./...
+
+test: ## Run test suite
+ @CGO_ENABLED=1 $(GOCMD) test -v -cover -race ./...
+
+coverage: ## Get test coverage report
+ @CGO_ENABLED=1 $(GOCMD) test -v -cover -race -cover -coverprofile=coverage.out ./...
+ @$(GOCMD) tool cover -html=coverage.out
+
+clean: ## Remove untracked files
+ @git clean -f -d -x
+
+clean-all: ## Remove untracked and Git ignores files
@git clean -f -d -X
diff --git a/README.md b/README.md
index 533b028..5bd8515 100644
--- a/README.md
+++ b/README.md
@@ -23,17 +23,7 @@ MP4 H.265 AAC, multiple collections and RSS feed.
## Getting Started
-### Using Homebrew
-
-```#!sh
-$ brew tap prologic/tube
-$ brew install tube
-$ tube
-```
-
-Open http://127.0.0.1:8000/ in your Browser!
-
-### Using a Binary
+### Prebuilt Release Binaries
1. Go grab the latest binary from the
[Releases](https://git.mills.io/prologic/tube/releases) page for your
@@ -43,28 +33,23 @@ Open http://127.0.0.1:8000/ in your Browser!
Open http://127.0.0.1:8000/ in your Browser!
-### Using Docker
+### Published Docker Images
```#!sh
$ docker pull prologic/tube
$ docker run -p 8000:8000 -v /path/to/data:/data
```
-or using makefile:
-
-``` make docker-run ```
-
-
Open http://DOCKER_MACHINE_IP:8000/ in your Browser!
Where `DOCKER_MACHINE_IP` is the IP Address of your Docker Node.
-### From Source
+### Building From Source
```#!sh
$ git clone https://git.mills.io/prologic/tube
$ cd tube
-$ make
+$ make build
$ ./tube
```
@@ -217,18 +202,6 @@ Set `path` to the value of the path where you want to store videos and where
}
}
-## Stargazers over time
-
-[![Stargazers over time](https://starcharts.herokuapp.com/prologic/tube.svg)](https://starcharts.herokuapp.com/prologic/tube)
-
-## Support
-
-Support the ongoing development of Tube!
-
-**Sponser**
-
-- Become a [Sponsor](https://www.patreon.com/prologic)
-
## Contributors
Thank you to all those that have contributed to this project, battle-tested it,
diff --git a/app/app.go b/app/app.go
index 26a6405..a431a1e 100644
--- a/app/app.go
+++ b/app/app.go
@@ -14,15 +14,15 @@ import (
"sort"
"strings"
+ "git.mills.io/prologic/tube/importers"
+ "git.mills.io/prologic/tube/media"
+ "git.mills.io/prologic/tube/utils"
rice "github.com/GeertJohan/go.rice"
"github.com/dustin/go-humanize"
"github.com/fsnotify/fsnotify"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
shortuuid "github.com/lithammer/shortuuid/v3"
- "git.mills.io/prologic/tube/importers"
- "git.mills.io/prologic/tube/media"
- "git.mills.io/prologic/tube/utils"
log "github.com/sirupsen/logrus"
)
@@ -298,11 +298,15 @@ func (a *App) uploadHandler(w http.ResponseWriter, r *http.Request) {
if err := utils.RunCmd(
a.Config.Thumbnailer.Timeout,
- "mt",
- "-b",
- "-s",
- "-n", "1",
- tf.Name(),
+ "ffmpeg",
+ "-i", uf.Name(),
+ "-y",
+ "-vf", "thumbnail",
+ "-t", "3",
+ "-vframes", "1",
+ "-strict", "-2",
+ "-loglevel", "quiet",
+ thumbFn1,
); err != nil {
err := fmt.Errorf("error generating thumbnail: %w", err)
log.Error(err)
diff --git a/main.go b/main.go
index ae23f86..0f9331f 100644
--- a/main.go
+++ b/main.go
@@ -42,8 +42,12 @@ func main() {
cfg := app.DefaultConfig()
err := cfg.ReadFile(config)
- if err != nil && !os.IsNotExist(err) {
- log.Fatal(err)
+ if err == nil {
+ log.Infof("reading configuration from %s", config)
+ } else {
+ if !os.IsNotExist(err) {
+ log.Fatal(err)
+ }
}
a, err := app.NewApp(cfg)
if err != nil {
diff --git a/media/library.go b/media/library.go
index 6bfedff..7de68e0 100644
--- a/media/library.go
+++ b/media/library.go
@@ -41,7 +41,7 @@ func (lib *Library) AddPath(p *Path) error {
return errors.New("media: duplicate library prefix")
}
}
- if err := os.MkdirAll(p.Path, 07550); err != nil {
+ if err := os.MkdirAll(p.Path, 0755); err != nil {
return fmt.Errorf("error creating library path %s: %w", p.Path, err)
}
lib.Paths[p.Path] = p
diff --git a/preflight.sh b/preflight.sh
new file mode 100755
index 0000000..f3b75f8
--- /dev/null
+++ b/preflight.sh
@@ -0,0 +1,135 @@
+#!/bin/sh
+
+set -e
+
+color() {
+ fg="$1"
+ bg="${2}"
+ ft="${3:-0}"
+
+ printf "\33[%s;%s;%s" "$ft" "$fg" "$bg"
+}
+
+color_reset() {
+ printf "\033[0m"
+}
+
+ok() {
+ if [ -t 1 ]; then
+ printf "%s[ OK ]%s\n" "$(color 37 42m 1)" "$(color_reset)"
+ else
+ printf "%s\n" "[ OK ]"
+ fi
+}
+
+err() {
+ if [ -t 1 ]; then
+ printf "%s[ ERR ]%s\n" "$(color 37 41m 1)" "$(color_reset)"
+ else
+ printf "%s\n" "[ ERR ]"
+ fi
+}
+
+run() {
+ retval=0
+ logfile="$(mktemp -t "run-XXXXXX")"
+ if "$@" 2> "$logfile"; then
+ ok
+ else
+ retval=$?
+ err
+ cat "$logfile" || true
+ fi
+ rm -rf "$logfile"
+ return $retval
+}
+
+progress() {
+ printf "%-40s" "$(printf "%s ... " "$1")"
+}
+
+log() {
+ printf "%s\n" "$1"
+}
+
+log2() {
+ printf "%s\n" "$1" 1>&2
+}
+
+error() {
+ log "ERROR: ${1}"
+}
+
+fail() {
+ log "FATAL: ${1}"
+ exit 1
+}
+
+check_goversion() {
+ progress "Checking Go version"
+
+ if ! command -v go > /dev/null 2>&1; then
+ log2 "Cannot find the Go compiler"
+ return 1
+ fi
+
+ gover="$(go version | grep -o -E 'go[0-9]+\.[0-9]+(\.[0-9]+)?')"
+
+ if ! go version | grep -E 'go1\.1[78](\.[0-9]+)?' > /dev/null; then
+ log2 "Go 1.17+ is required, found ${gover}"
+ return 1
+ fi
+
+ return 0
+}
+
+check_path() {
+ progress "Checking \$PATH"
+
+ gobin="$(eval "$(go env | grep GOBIN)")"
+ gopath="$(eval "$(go env | grep GOPATH)")"
+
+ if [ -n "$gobin" ] && ! echo "$PATH" | grep "$gobin" > /dev/null; then
+ log2 "\$GOBIN '$gobin' is not in your \$PATH"
+ return 1
+ fi
+
+ if [ -n "$gopath" ] && ! echo "$PATH" | grep "$gopath/bin" > /dev/null; then
+ log2 "\$GOPATH/bin '$gopath/bin' is not in your \$PATH"
+ return 1
+ fi
+
+ if ! echo "$PATH" | grep "$HOME/go/bin" > /dev/null; then
+ log2 "\$HOME/go/bin is not in your \$PATH"
+ return 1
+ fi
+
+ return 0
+}
+
+check_deps() {
+ progress "Checking deps"
+
+ if ! command -v ffmpeg > /dev/null 2>&1; then
+ log2 "ffmpeg not found, Please install it using your OS package manager"
+ return 1
+ fi
+
+ return 0
+}
+
+steps="check_goversion check_path check_deps"
+
+_main() {
+ for step in $steps; do
+ if ! run "$step"; then
+ fail "🙁 preflight failed"
+ fi
+ done
+
+ log "🥳 All Done! Ready to build, run: make build"
+}
+
+if [ -n "$0" ] && [ x"$0" != x"-bash" ]; then
+ _main "$@"
+fi
diff --git a/tools/release.sh b/tools/release.sh
index e8ab44e..77d8612 100755
--- a/tools/release.sh
+++ b/tools/release.sh
@@ -1,16 +1,19 @@
-#!/bin/sh
+#!/bin/bash
# Get the highest tag number
VERSION="$(git describe --abbrev=0 --tags)"
VERSION=${VERSION:-'0.0.0'}
# Get number parts
-MAJOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
-MINOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
-PATCH="${VERSION%%.*}"; VERSION="${VERSION#*.}"
+MAJOR="${VERSION%%.*}"
+VERSION="${VERSION#*.}"
+MINOR="${VERSION%%.*}"
+VERSION="${VERSION#*.}"
+PATCH="${VERSION%%.*}"
+VERSION="${VERSION#*.}"
# Increase version
-PATCH=$((PATCH+1))
+PATCH=$((PATCH + 1))
TAG="${1}"
@@ -20,6 +23,10 @@ fi
echo "Releasing ${TAG} ..."
+git-chglog --next-tag="${TAG}" --output CHANGELOG.md
+git commit -a -m "Update CHANGELOG for ${TAG}"
git tag -a -s -m "Release ${TAG}" "${TAG}"
-git push --tags
-goreleaser release --rm-dist
+git push && git push --tags
+goreleaser release \
+ --rm-dist \
+ --release-notes <(git-chglog "${TAG}" | tail -n+5)