1

Initial commit

This commit is contained in:
2025-06-13 04:15:35 +04:00
commit 1c350b8dfb
14 changed files with 500 additions and 0 deletions

42
lib/app/app.go Normal file
View File

@@ -0,0 +1,42 @@
package app
import (
"context"
"github.com/sirupsen/logrus"
"source.hodakov.me/hdkv/github-release/lib/settings"
)
type App struct {
ctx context.Context
logger *logrus.Logger
settings *settings.Settings
}
func (a *App) Context() context.Context {
return a.ctx
}
func (a *App) Logger() *logrus.Logger {
return a.logger
}
func (a *App) Settings() *settings.Settings {
return a.settings
}
func Init(ctx context.Context) *App {
app := new(App)
app.settings = new(settings.Settings)
app.logger = logrus.StandardLogger()
app.logger.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})
app.ctx = ctx
return app
}

37
lib/github/connect.go Normal file
View File

@@ -0,0 +1,37 @@
package github
import (
"context"
"net/http"
"net/url"
"github.com/google/go-github/v72/github"
"golang.org/x/oauth2"
)
func (g *Github) Connect() error {
httpClient := new(http.Client)
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: g.app.Settings().APIKey})
tc := oauth2.NewClient(
context.WithValue(g.app.Context(), oauth2.HTTPClient, httpClient), ts,
)
client := github.NewClient(tc)
var err error
client.BaseURL, err = url.Parse("https://api.github.com/")
if err != nil {
return err
}
client.UploadURL, err = url.Parse("https://uploads.github.com/")
if err != nil {
return err
}
g.client = client
return nil
}

17
lib/github/github.go Normal file
View File

@@ -0,0 +1,17 @@
package github
import (
"github.com/google/go-github/v72/github"
"source.hodakov.me/hdkv/github-release/lib/app"
)
type Github struct {
app *app.App
client *github.Client
}
func New(app *app.App) *Github {
return &Github{
app: app,
}
}

32
lib/github/release.go Normal file
View File

@@ -0,0 +1,32 @@
package github
import (
"github.com/google/go-github/v72/github"
)
func (g *Github) Release() (*int64, error) {
relInfo := &github.RepositoryRelease{
Name: &g.app.Settings().Title,
Body: &g.app.Settings().Description,
Draft: &g.app.Settings().Draft,
TagName: &g.app.Settings().Tag,
}
if *relInfo.Draft {
g.app.Logger().Info("Release will be created as draft (unpublished) release")
} else {
g.app.Logger().Info("Release will be created and published")
}
release, _, err := g.client.Repositories.CreateRelease(
g.app.Context(), g.app.Settings().Owner, g.app.Settings().Repo, relInfo)
if err != nil {
g.app.Logger().WithError(err).Error("Failed to create release")
return nil, err
}
g.app.Logger().WithField("release-id", *release.ID).Info("Successfully created release")
return release.ID, nil
}

83
lib/github/upload.go Normal file
View File

@@ -0,0 +1,83 @@
package github
import (
"fmt"
"os"
"github.com/google/go-github/v72/github"
)
func (g *Github) Upload(releaseID int64) error {
var assets []*github.ReleaseAsset
listOpts := &github.ListOptions{}
for {
asset, resp, err := g.client.Repositories.ListReleaseAssets(
g.app.Context(), g.app.Settings().Owner, g.app.Settings().Repo,
releaseID, listOpts,
)
if err != nil {
g.app.Logger().WithError(err).Error("Failed to fetch existing assets")
return err
}
assets = append(assets, asset...)
if resp.NextPage == 0 {
break
}
listOpts.Page = resp.NextPage
}
uploadFiles, err := os.ReadDir(g.app.Settings().Storage)
if err != nil {
g.app.Logger().WithError(err).Error("Failed to read assets storage")
}
for _, file := range uploadFiles {
if !file.IsDir() {
for _, asset := range assets {
if file.Name() == *asset.Name {
g.app.Logger().WithField("name", file.Name()).Error("File exists")
return fmt.Errorf("file exists: %s", file.Name())
}
}
}
}
for _, file := range uploadFiles {
if file.IsDir() {
continue
}
fileReader, err := os.Open(
fmt.Sprintf("%s/%s", g.app.Settings().Storage, file.Name()),
)
if err != nil {
g.app.Logger().
WithError(err).WithField("name", file.Name()).
Error("Failed to read artifact")
return err
}
uploadOptions := &github.UploadOptions{Name: file.Name()}
if _, _, err = g.client.Repositories.UploadReleaseAsset(
g.app.Context(), g.app.Settings().Owner, g.app.Settings().Repo,
releaseID, uploadOptions, fileReader); err != nil {
g.app.Logger().
WithError(err).WithField("name", file.Name()).
Error("Failed to upload artifact")
return err
}
g.app.Logger().WithField("name", file.Name()).Info("Successfully uploaded artifact")
}
return nil
}

20
lib/settings/settings.go Normal file
View File

@@ -0,0 +1,20 @@
package settings
import (
"github.com/caarlos0/env/v11"
)
type Settings struct {
APIKey string `env:"RELEASER_API_KEY,required"`
Owner string `env:"RELEASER_OWNER,required"`
Repo string `env:"RELEASER_REPO,required"`
Tag string `env:"RELEASER_TAG,required"`
Draft bool `env:"RELEASER_DRAFT,required"`
Title string `env:"RELEASER_TITLE,required"`
Description string `env:"RELEASER_DESCRIPTION,required"`
Storage string `env:"RELEASER_STORAGE,required"`
}
func (s *Settings) Populate() error {
return env.Parse(s)
}