Compare commits

...
23 Commits
Author SHA1 Message Date
Svilen Markov b37f8a8375 Merge pull request #194 from glanceapp/backport-fixes
Create release / release (push) Has been cancelled
Backport fixes from v0.6.0 to v0.5.0
2024-08-09 16:08:30 +01:00
Svilen Markov 139937f887 Fix missing RSS thumbnail images 2024-08-09 16:03:24 +01:00
Wyatt Gill b8b90451b6 Use GitHub's latest release API endpoint
The current releases widget uses the releases endpoint to pull the 10
most recent releases and filter them to find the latest release. This
causes a problem when a repository's latest release is outside of the 10
most recent (e.g. 10 prereleases):

ERROR No live release found repository=cross-seed/cross-seed url="https://api.github.com/repos/cross-seed/cross-seed/releases?per_page=10"

This is no longer a problem when using the latest release endpoint which
grabs the latest release, ignoring draft releases and prereleases.
2024-08-09 16:02:15 +01:00
Svilen Markov c9a2aff6a6 Fix search input color 2024-08-09 16:01:15 +01:00
Svilen Markov 82b6531a07 Add funding 2024-08-07 19:18:17 +01:00
Svilen Markov a981025679 Merge pull request #108 from wfg/github-actions
Create release workflow
2024-08-07 18:58:13 +01:00
Svilen Markov f9ea2d73e1 Tidy up previous build files 2024-08-07 18:50:06 +01:00
Svilen Markov a5728e9407 Update release workflow 2024-08-07 18:47:50 +01:00
Svilen Markov 1411268e35 Merge pull request #80 from c0smicdev/main
Add Kanagawa Dark theme
2024-07-03 19:51:42 +01:00
c0smic 645802981e Update theme preview 2024-06-14 16:56:33 +00:00
c0smic 0348a2475c Delete preview of old version 2024-06-14 16:55:44 +00:00
Svilen Markov 6c15c907bf Remove clock from preconfigured page 2024-06-11 00:17:25 +01:00
Wyatt Gill d5cf881d7a Produce example 2024-06-03 16:16:43 -05:00
Wyatt Gill 050d3e6cd2 Add release workflow using GoReleaser 2024-06-03 16:16:43 -05:00
c0smic d27993d2c9 fix: use negative color with higher contrast 2024-05-29 16:53:31 +00:00
c0smic bfc65d51e3 Merge branch 'glanceapp:main' into main 2024-05-29 16:50:18 +00:00
c0smicandSvilen Markov 3c29d38599 fix: Fix typo
Co-authored-by: Svilen Markov <7613769+svilenmarkov@users.noreply.github.com>
2024-05-27 18:11:35 +00:00
c0smic 060609e2cb Add Kanagawa Dark to themes 2024-05-18 14:25:08 +00:00
c0smic a1c48bf012 Use new Kanagawa Dark Image 2024-05-18 14:24:15 +00:00
c0smic a67fb66d2e Delete old Kanagawa Dark image 2024-05-18 14:23:32 +00:00
c0smic 3001f4845a Add new Kanagawa Dark image 2024-05-18 14:20:17 +00:00
c0smic 192c1ad669 Rename kanagawa dark preview image 2024-05-18 14:15:35 +00:00
c0smic 89ae8a3607 Add Kanagawa Dark Theme preview 2024-05-18 14:13:56 +00:00
14 changed files with 177 additions and 348 deletions
+1
View File
@@ -0,0 +1 @@
github: [glanceapp]
+39
View File
@@ -0,0 +1,39 @@
name: Create release
permissions:
contents: write
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout the target Git reference
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Golang
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Set up Docker buildx
uses: docker/setup-buildx-action@v3
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
args: release
+72
View File
@@ -0,0 +1,72 @@
project_name: glanceapp/glance
checksum:
disable: true
builds:
- binary: glance
env:
- CGO_ENABLED=0
goos:
- linux
- openbsd
- freebsd
- windows
- darwin
goarch:
- amd64
- arm64
- arm
- 386
goarm:
- 7
ldflags:
- -s -w -X github.com/glanceapp/glance/internal/glance.buildVersion={{ .Tag }}
archives:
-
name_template: "glance-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}"
files:
- nothing*
format_overrides:
- goos: windows
format: zip
dockers:
- image_templates:
- &amd64_image "{{ .ProjectName }}:{{ .Tag }}-amd64"
build_flag_templates:
- --platform=linux/amd64
goarch: amd64
use: buildx
dockerfile: Dockerfile.goreleaser
- image_templates:
- &arm64v8_image "{{ .ProjectName }}:{{ .Tag }}-arm64"
build_flag_templates:
- --platform=linux/arm64
goarch: arm64
use: buildx
dockerfile: Dockerfile.goreleaser
- image_templates:
- &arm64v7_image "{{ .ProjectName }}:{{ .Tag }}-arm64v7"
build_flag_templates:
- --platform=linux/arm64/v7
goarch: arm
goarm: 7
use: buildx
dockerfile: Dockerfile.goreleaser
docker_manifests:
- name_template: "{{ .ProjectName }}:{{ .Tag }}"
image_templates:
- *amd64_image
- *arm64v8_image
- *arm64v7_image
- name_template: "{{ .ProjectName }}:latest"
skip_push: auto
image_templates:
- *amd64_image
- *arm64v8_image
- *arm64v7_image
+8 -6
View File
@@ -1,11 +1,13 @@
FROM alpine:3.20 FROM golang:1.22.5-alpine3.20 AS builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
WORKDIR /app WORKDIR /app
COPY build/glance-$TARGETOS-$TARGETARCH${TARGETVARIANT} /app/glance COPY . /app
RUN CGO_ENABLED=0 go build .
FROM alpine:3.20
WORKDIR /app
COPY --from=builder /app/glance .
EXPOSE 8080/tcp EXPOSE 8080/tcp
ENTRYPOINT ["/app/glance"] ENTRYPOINT ["/app/glance"]
+8
View File
@@ -0,0 +1,8 @@
FROM alpine:3.20
WORKDIR /app
COPY glance .
EXPOSE 8080/tcp
ENTRYPOINT ["/app/glance"]
-14
View File
@@ -1,14 +0,0 @@
FROM golang:1.22.3-alpine3.19 AS builder
WORKDIR /app
COPY . /app
RUN CGO_ENABLED=0 go build .
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/glance .
EXPOSE 8080/tcp
ENTRYPOINT ["/app/glance"]
+1 -1
View File
@@ -101,7 +101,7 @@ Build the image:
**Make sure to replace "owner" with your name or organization.** **Make sure to replace "owner" with your name or organization.**
```bash ```bash
docker build -t owner/glance:latest -f Dockerfile.single-platform . docker build -t owner/glance:latest .
``` ```
Push the image to your registry: Push the image to your registry:
-1
View File
@@ -40,7 +40,6 @@ pages:
columns: columns:
- size: small - size: small
widgets: widgets:
- type: clock
- type: calendar - type: calendar
- type: rss - type: rss
Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

+10
View File
@@ -53,6 +53,16 @@ theme:
primary-color: 97 13 80 primary-color: 97 13 80
``` ```
### Kanagawa Dark
![screenshot](images/themes/kanagawa-dark.png)
```yaml
theme:
background-color: 240 13 14
primary-color: 51 33 68
negative-color: 358 100 68
contrast-multiplier: 1.2
```
### Tucan ### Tucan
![screenshot](images/themes/tucan.png) ![screenshot](images/themes/tucan.png)
```yaml ```yaml
+1
View File
@@ -731,6 +731,7 @@ kbd:active {
height: 6rem; height: 6rem;
font: inherit; font: inherit;
outline: none; outline: none;
color: var(--color-text-highlight);
} }
.search-input::placeholder { .search-input::placeholder {
+4 -23
View File
@@ -8,12 +8,10 @@ import (
"time" "time"
) )
type githubReleaseResponseJson struct { type githubReleaseLatestResponseJson struct {
TagName string `json:"tag_name"` TagName string `json:"tag_name"`
PublishedAt string `json:"published_at"` PublishedAt string `json:"published_at"`
HtmlUrl string `json:"html_url"` HtmlUrl string `json:"html_url"`
Draft bool `json:"draft"`
PreRelease bool `json:"prerelease"`
Reactions struct { Reactions struct {
Downvotes int `json:"-1"` Downvotes int `json:"-1"`
} `json:"reactions"` } `json:"reactions"`
@@ -39,7 +37,7 @@ func FetchLatestReleasesFromGithub(repositories []string, token string) (AppRele
requests := make([]*http.Request, len(repositories)) requests := make([]*http.Request, len(repositories))
for i, repository := range repositories { for i, repository := range repositories {
request, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s/releases?per_page=10", repository), nil) request, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", repository), nil)
if token != "" { if token != "" {
request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
@@ -48,7 +46,7 @@ func FetchLatestReleasesFromGithub(repositories []string, token string) (AppRele
requests[i] = request requests[i] = request
} }
task := decodeJsonFromRequestTask[[]githubReleaseResponseJson](defaultClient) task := decodeJsonFromRequestTask[githubReleaseLatestResponseJson](defaultClient)
job := newJob(task, requests).withWorkers(15) job := newJob(task, requests).withWorkers(15)
responses, errs, err := workerPoolDo(job) responses, errs, err := workerPoolDo(job)
@@ -65,24 +63,7 @@ func FetchLatestReleasesFromGithub(repositories []string, token string) (AppRele
continue continue
} }
releases := responses[i] liveRelease := &responses[i]
if len(releases) < 1 {
failed++
slog.Error("No releases found", "repository", repositories[i], "url", requests[i].URL)
continue
}
var liveRelease *githubReleaseResponseJson
for i := range releases {
release := &releases[i]
if !release.Draft && !release.PreRelease {
liveRelease = release
break
}
}
if liveRelease == nil { if liveRelease == nil {
slog.Error("No live release found", "repository", repositories[i], "url", requests[i].URL) slog.Error("No live release found", "repository", repositories[i], "url", requests[i].URL)
+33
View File
@@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/mmcdole/gofeed" "github.com/mmcdole/gofeed"
gofeedext "github.com/mmcdole/gofeed/extensions"
) )
type RSSFeedItem struct { type RSSFeedItem struct {
@@ -145,6 +146,8 @@ func getItemsFromRSSFeedTask(request RSSFeedRequest) ([]RSSFeedItem, error) {
if item.Image != nil { if item.Image != nil {
rssItem.ImageURL = item.Image.URL rssItem.ImageURL = item.Image.URL
} else if url := findThumbnailInItemExtensions(item); url != "" {
rssItem.ImageURL = url
} else if feed.Image != nil { } else if feed.Image != nil {
rssItem.ImageURL = feed.Image.URL rssItem.ImageURL = feed.Image.URL
} }
@@ -161,6 +164,36 @@ func getItemsFromRSSFeedTask(request RSSFeedRequest) ([]RSSFeedItem, error) {
return items, nil return items, nil
} }
func recursiveFindThumbnailInExtensions(extensions map[string][]gofeedext.Extension) string {
for _, exts := range extensions {
for _, ext := range exts {
if ext.Name == "thumbnail" || ext.Name == "image" {
if url, ok := ext.Attrs["url"]; ok {
return url
}
}
if ext.Children != nil {
if url := recursiveFindThumbnailInExtensions(ext.Children); url != "" {
return url
}
}
}
}
return ""
}
func findThumbnailInItemExtensions(item *gofeed.Item) string {
media, ok := item.Extensions["media"]
if !ok {
return ""
}
return recursiveFindThumbnailInExtensions(media)
}
func GetItemsFromRSSFeeds(requests []RSSFeedRequest) (RSSFeedItems, error) { func GetItemsFromRSSFeeds(requests []RSSFeedRequest) (RSSFeedItems, error) {
job := newJob(getItemsFromRSSFeedTask, requests).withWorkers(10) job := newJob(getItemsFromRSSFeedTask, requests).withWorkers(10)
feeds, errs, err := workerPoolDo(job) feeds, errs, err := workerPoolDo(job)
-303
View File
@@ -1,303 +0,0 @@
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path"
"strings"
)
// bunch of spaget but it does the job for now
// TODO: tidy up and add a proper build system with CI
const buildPath = "./build"
const archivesPath = "./build/archives"
const executableName = "glance"
const ownerAndRepo = "glanceapp/glance"
const moduleName = "github.com/" + ownerAndRepo
type archiveType int
const (
archiveTypeTarGz archiveType = iota
archiveTypeZip
)
type buildInfo struct {
version string
}
type buildTarget struct {
os string
arch string
armV int
extension string
archive archiveType
}
var buildTargets = []buildTarget{
{
os: "windows",
arch: "amd64",
extension: ".exe",
archive: archiveTypeZip,
},
{
os: "windows",
arch: "arm64",
extension: ".exe",
archive: archiveTypeZip,
},
{
os: "linux",
arch: "amd64",
},
{
os: "linux",
arch: "arm64",
},
{
os: "linux",
arch: "arm",
armV: 6,
},
{
os: "linux",
arch: "arm",
armV: 7,
},
{
os: "openbsd",
arch: "amd64",
},
{
os: "openbsd",
arch: "386",
},
}
func hasUncommitedChanges() (bool, error) {
output, err := exec.Command("git", "status", "--porcelain").CombinedOutput()
if err != nil {
return false, err
}
return len(output) > 0, nil
}
func main() {
flags := flag.NewFlagSet("", flag.ExitOnError)
specificTag := flags.String("tag", "", "Which tagged version to build")
err := flags.Parse(os.Args[1:])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
uncommitedChanges, err := hasUncommitedChanges()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if uncommitedChanges {
fmt.Println("There are uncommited changes - commit, stash or discard them first")
os.Exit(1)
}
cwd, err := os.Getwd()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
_, err = os.Stat(buildPath)
if err == nil {
fmt.Println("Cleaning up build path")
os.RemoveAll(buildPath)
}
os.Mkdir(buildPath, 0755)
os.Mkdir(archivesPath, 0755)
var version string
if *specificTag == "" {
version, err := getVersionFromGit()
if err != nil {
fmt.Println(version, err)
os.Exit(1)
}
} else {
version = *specificTag
}
output, err := exec.Command("git", "checkout", "tags/"+version).CombinedOutput()
if err != nil {
fmt.Println(string(output))
fmt.Println(err)
os.Exit(1)
}
info := buildInfo{
version: version,
}
for _, target := range buildTargets {
fmt.Printf("Building for %s/%s\n", target.os, target.arch)
if err := build(cwd, info, target); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
versionTag := fmt.Sprintf("%s:%s", ownerAndRepo, version)
latestTag := fmt.Sprintf("%s:latest", ownerAndRepo)
fmt.Println("Building docker image")
var dockerBuildOptions = []string{
"docker", "build",
"--platform=linux/amd64,linux/arm64,linux/arm/v7",
"-t", versionTag,
}
if !strings.Contains(version, "beta") {
dockerBuildOptions = append(dockerBuildOptions, "-t", latestTag)
}
dockerBuildOptions = append(dockerBuildOptions, ".")
output, err = exec.Command("sudo", dockerBuildOptions...).CombinedOutput()
if err != nil {
fmt.Println(string(output))
fmt.Println(err)
os.Exit(1)
}
var input string
fmt.Print("Push docker image? [y/n]: ")
fmt.Scanln(&input)
if input != "y" {
os.Exit(0)
}
output, err = exec.Command(
"sudo", "docker", "push", versionTag,
).CombinedOutput()
if err != nil {
fmt.Printf("Failed pushing %s:\n", versionTag)
fmt.Println(string(output))
fmt.Println(err)
os.Exit(1)
}
if strings.Contains(version, "beta") {
return
}
output, err = exec.Command(
"sudo", "docker", "push", latestTag,
).CombinedOutput()
if err != nil {
fmt.Printf("Failed pushing %s:\n", latestTag)
fmt.Println(string(output))
fmt.Println(err)
os.Exit(1)
}
}
func getVersionFromGit() (string, error) {
output, err := exec.Command("git", "describe", "--tags", "--abbrev=0").CombinedOutput()
if err == nil {
return strings.TrimSpace(string(output)), err
}
return string(output), err
}
func archiveFile(name string, target string, t archiveType) error {
var output []byte
var err error
if t == archiveTypeZip {
output, err = exec.Command("zip", "-j", path.Join(archivesPath, name+".zip"), target).CombinedOutput()
} else if t == archiveTypeTarGz {
output, err = exec.Command("tar", "-C", buildPath, "-czf", path.Join(archivesPath, name+".tar.gz"), name).CombinedOutput()
}
if err != nil {
fmt.Println(string(output))
return err
}
return nil
}
func build(workingDir string, info buildInfo, target buildTarget) error {
var name string
if target.arch != "arm" {
name = fmt.Sprintf("%s-%s-%s%s", executableName, target.os, target.arch, target.extension)
} else {
name = fmt.Sprintf("%s-%s-%sv%d", executableName, target.os, target.arch, target.armV)
}
binaryPath := path.Join(buildPath, name)
glancePackage := moduleName + "/internal/glance"
flags := "-s -w"
flags += fmt.Sprintf(" -X %s.buildVersion=%s", glancePackage, info.version)
cmd := exec.Command(
"go",
"build",
"--trimpath",
"--ldflags",
flags,
"-o",
binaryPath,
)
cmd.Dir = workingDir
env := append(os.Environ(), "GOOS="+target.os, "GOARCH="+target.arch, "CGO_ENABLED=0")
if target.arch == "arm" {
env = append(env, fmt.Sprintf("GOARM=%d", target.armV))
}
cmd.Env = env
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err)
fmt.Println(string(output))
return err
}
os.Chmod(binaryPath, 0755)
fmt.Println("Creating archive")
if err := archiveFile(name, binaryPath, target.archive); err != nil {
return err
}
return nil
}