Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
floodcode committed Mar 25, 2024
0 parents commit b573049
Show file tree
Hide file tree
Showing 12 changed files with 445 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Build Docker Image

on:
push:
tags:
- '*'

jobs:
build-source:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:${{ github.ref_name }},${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:latest
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bin/
/config.yml
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM golang:1.22

WORKDIR /app

COPY cmd/ cmd/
COPY internal/ internal/

COPY go.mod go.mod
COPY go.sum go.sum
RUN go mod download

RUN go install -v /app/cmd/service

CMD ["service"]
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.PHONY: help
help: # Display this help
@awk 'BEGIN{FS=":.*#";printf "Usage:\n make <target>\n\nTargets:\n"}/^[a-zA-Z_-]+:.*?#/{printf" %-10s %s\n",$$1,$$2}' $(MAKEFILE_LIST)

.PHONY: build
build: # Build service to bin/ directory
go build -o bin/service cmd/service/main.go

.PHONY: run
run: build # Runs service after build
./bin/service
53 changes: 53 additions & 0 deletions cmd/service/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"flag"
"net/http"
"os"
"time"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/gorilla/mux"

"github.com/ATOR-Development/anon-download-links/internal/api"
"github.com/ATOR-Development/anon-download-links/internal/config"
"github.com/ATOR-Development/anon-download-links/internal/downloads"
)

var (
configFile = flag.String("config", "config.yml", "Config file.")
listenAddress = flag.String("listen-address", ":8080", "Exporter HTTP listen address.")
)

func main() {
flag.Parse()

logger := log.NewLogfmtLogger(os.Stderr)
logger = log.WithPrefix(logger, "ts", log.TimestampFormat(time.Now, time.Stamp))

level.Info(logger).Log("msg", "initializing service from", "config", *configFile)

cfg, err := config.FromFile(*configFile)
if err != nil {
level.Error(logger).Log("msg", "cannot read config", "err", err.Error())
os.Exit(1)
}

downloads, err := downloads.New(cfg, logger)
if err != nil {
level.Error(logger).Log("msg", "cannot create downloads service", "err", err.Error())
os.Exit(1)
}

level.Info(logger).Log("msg", "starting http server", "listen", *listenAddress)

api := api.New(downloads, logger)

router := mux.NewRouter()
router.HandleFunc("/api/downloads", api.HandleDownloads).Methods("GET")
router.HandleFunc("/download/{name}", api.HandleDownload).Methods("GET")

http.Handle("/", router)
http.ListenAndServe(*listenAddress, nil)
}
26 changes: 26 additions & 0 deletions config.example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
owner: ATOR-Development
repo: ator-protocol
cachePeriod: 1m
artifacts:
- name: macos-amd64
regexp: '^anon-live-macos-amd64.+'
- name: macos-arm64
regexp: '^anon-live-macos-arm64.+'
- name: windows-amd64
regexp: '^anon-live-windows-amd64.+'
- name: debian-bullseye-amd64
regexp: '^anon.+-live-.+bullseye.+amd64\.deb'
- name: debian-bullseye-arm64
regexp: '^anon.+-live-.+bullseye.+arm64\.deb'
- name: debian-bookworm-amd64
regexp: '^anon.+-live-.+bookworm.+amd64\.deb'
- name: debian-bookworm-arm64
regexp: '^anon.+-live-.+bookworm.+arm64\.deb'
- name: ubuntu-focal-amd64
regexp: '^anon.+-live-.+focal.+amd64\.deb'
- name: ubuntu-focal-arm64
regexp: '^anon.+-live-.+focal.+arm64\.deb'
- name: ubuntu-jammy-amd64
regexp: '^anon.+-live-.+jammy.+amd64\.deb'
- name: ubuntu-jammy-arm64
regexp: '^anon.+-live-.+jammy.+arm64\.deb'
11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/ATOR-Development/anon-download-links

go 1.20

require (
github.com/go-kit/log v0.2.1
github.com/gorilla/mux v1.8.1
gopkg.in/yaml.v3 v3.0.1
)

require github.com/go-logfmt/logfmt v0.5.1 // indirect
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
73 changes: 73 additions & 0 deletions internal/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package api

import (
"encoding/json"
"net/http"

"github.com/ATOR-Development/anon-download-links/internal/downloads"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/gorilla/mux"
)

type API struct {
downloads *downloads.Downloads

logger log.Logger
}

func New(downloads *downloads.Downloads, logger log.Logger) *API {
return &API{
downloads: downloads,

logger: log.WithPrefix(logger, "service", "api"),
}
}

func (a *API) HandleDownloads(w http.ResponseWriter, r *http.Request) {
level.Error(a.logger).Log("msg", "handling downloads")

artifacts, err := a.downloads.GetArtifacts(r.Context())
if err != nil {
level.Error(a.logger).Log("msg", "unable to get artifacts", "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

respBytes, err := json.Marshal(artifacts)
if err != nil {
level.Error(a.logger).Log("msg", "unable to marshal artifacts", "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

w.Write(respBytes)
}

func (a *API) HandleDownload(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name, ok := vars["name"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
return
}

level.Error(a.logger).Log("msg", "handling download", "name", name)

artifactsMap, err := a.downloads.GetArtifactsMap(r.Context())
if err != nil {
level.Error(a.logger).Log("msg", "unable to get artifacts map", "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

downloadURL, ok := artifactsMap[name]
if !ok {
level.Warn(a.logger).Log("msg", "download not found", "name", name)
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("download not found"))
return
}

http.Redirect(w, r, downloadURL, http.StatusFound)
}
46 changes: 46 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package config

import (
"fmt"
"os"

"gopkg.in/yaml.v3"
)

type Config struct {
Owner string `yaml:"owner"`
Repo string `yaml:"repo"`
CachePeriod string `yaml:"cachePeriod"`
Artifacts []Artifact `yaml:"artifacts"`
}

type Artifact struct {
Name string `yaml:"name"`
Regexp string `yaml:"regexp"`
}

// New creates new Config from config data
func New(data []byte) (*Config, error) {
var cfg Config
err := yaml.Unmarshal(data, &cfg)
if err != nil {
return nil, err
}

return &cfg, nil
}

// FromFile reads filename and creates Config from it
func FromFile(filename string) (*Config, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}

cfg, err := New(data)
if err != nil {
return nil, fmt.Errorf("%s: %w", filename, err)
}

return cfg, nil
}
Loading

0 comments on commit b573049

Please sign in to comment.