Skip to content

Commit 581b7ed

Browse files
refactor: split plugin discovery in differen files
1 parent 9408101 commit 581b7ed

File tree

6 files changed

+269
-239
lines changed

6 files changed

+269
-239
lines changed

pkg/hooks/hooks.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,21 @@ type ChainedHooksExecutor struct {
1616

1717
func (c *ChainedHooksExecutor) Success(config *SuccessHookConfig) error {
1818
for _, h := range c.HooksChain {
19+
name := h.Name()
1920
err := h.Success(config)
2021
if err != nil {
21-
return err
22+
return fmt.Errorf("%s hook has failed: %w", name, err)
2223
}
2324
}
2425
return nil
2526
}
2627

2728
func (c *ChainedHooksExecutor) NoRelease(config *NoReleaseConfig) error {
2829
for _, h := range c.HooksChain {
30+
name := h.Name()
2931
err := h.NoRelease(config)
3032
if err != nil {
31-
return err
33+
return fmt.Errorf("%s hook has failed: %w", name, err)
3234
}
3335
}
3436
return nil

pkg/plugin/discovery/discovery.go

Lines changed: 2 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
11
package discovery
22

33
import (
4-
"crypto/sha256"
5-
"encoding/hex"
6-
"encoding/json"
74
"errors"
8-
"fmt"
9-
"io/ioutil"
10-
"net/http"
11-
"os"
125
"os/exec"
13-
"path"
14-
"runtime"
15-
"sort"
166
"strings"
17-
"time"
187

198
"github.com/Masterminds/semver/v3"
20-
"github.com/cavaliergopher/grab/v3"
219
"github.com/go-semantic-release/semantic-release/v2/pkg/analyzer"
2210
"github.com/go-semantic-release/semantic-release/v2/pkg/condition"
2311
"github.com/go-semantic-release/semantic-release/v2/pkg/config"
@@ -26,56 +14,8 @@ import (
2614
"github.com/go-semantic-release/semantic-release/v2/pkg/plugin"
2715
"github.com/go-semantic-release/semantic-release/v2/pkg/provider"
2816
"github.com/go-semantic-release/semantic-release/v2/pkg/updater"
29-
"github.com/schollz/progressbar/v3"
3017
)
3118

32-
const PluginDir = ".semrel"
33-
const PluginAPI = "https://plugins.go-semantic-release.xyz/api/v1"
34-
35-
var osArchDir = runtime.GOOS + "_" + runtime.GOARCH
36-
37-
func getPluginPath(name string) string {
38-
pElem := append([]string{PluginDir}, osArchDir, name)
39-
return path.Join(pElem...)
40-
}
41-
42-
func ensurePluginDir(pth string) error {
43-
_, err := os.Stat(pth)
44-
if os.IsNotExist(err) {
45-
return os.MkdirAll(pth, 0755)
46-
}
47-
return err
48-
}
49-
50-
type apiPluginAsset struct {
51-
FileName string
52-
URL string
53-
OS string
54-
Arch string
55-
Checksum string
56-
}
57-
58-
type apiPluginRelease struct {
59-
CreatedAt time.Time
60-
Assets []*apiPluginAsset
61-
}
62-
63-
func (r *apiPluginRelease) getMatchingAsset() *apiPluginAsset {
64-
for _, a := range r.Assets {
65-
if a.OS == runtime.GOOS && a.Arch == runtime.GOARCH {
66-
return a
67-
}
68-
}
69-
return nil
70-
}
71-
72-
type apiPlugin struct {
73-
Type string
74-
Name string
75-
LatestRelease string
76-
Versions map[string]*apiPluginRelease
77-
}
78-
7919
type Discovery struct {
8020
config *config.Config
8121
}
@@ -84,178 +24,6 @@ func New(config *config.Config) (*Discovery, error) {
8424
return &Discovery{config}, nil
8525
}
8626

87-
func (d *Discovery) getPluginInfo(name string) (*apiPlugin, error) {
88-
res, err := http.Get(fmt.Sprintf("%s/plugins/%s.json", PluginAPI, name))
89-
if err != nil {
90-
return nil, err
91-
}
92-
defer res.Body.Close()
93-
if res.StatusCode == 404 {
94-
return nil, fmt.Errorf("plugin not found: %s", name)
95-
}
96-
if res.StatusCode < 200 || res.StatusCode >= 300 {
97-
return nil, errors.New("invalid response")
98-
}
99-
var plugin *apiPlugin
100-
if err := json.NewDecoder(res.Body).Decode(&plugin); err != nil {
101-
return nil, err
102-
}
103-
return plugin, nil
104-
}
105-
106-
func showDownloadProgressBar(name string, res *grab.Response) {
107-
bar := progressbar.NewOptions64(
108-
res.Size(),
109-
progressbar.OptionSetDescription(name),
110-
progressbar.OptionSetWriter(os.Stderr),
111-
progressbar.OptionShowBytes(true),
112-
progressbar.OptionSetWidth(10),
113-
progressbar.OptionThrottle(65*time.Millisecond),
114-
progressbar.OptionShowCount(),
115-
progressbar.OptionSetWidth(40),
116-
progressbar.OptionClearOnFinish(),
117-
progressbar.OptionSetPredictTime(false),
118-
)
119-
t := time.NewTicker(100 * time.Millisecond)
120-
done := make(chan struct{})
121-
go func() {
122-
for {
123-
select {
124-
case <-t.C:
125-
_ = bar.Set64(res.BytesComplete())
126-
case <-res.Done:
127-
_ = bar.Finish()
128-
t.Stop()
129-
done <- struct{}{}
130-
return
131-
}
132-
}
133-
}()
134-
<-done
135-
}
136-
137-
func (d *Discovery) fetchPlugin(name, pth string, cons *semver.Constraints) (string, error) {
138-
pluginInfo, err := d.getPluginInfo(name)
139-
if err != nil {
140-
return "", err
141-
}
142-
143-
foundVersion := ""
144-
if cons == nil {
145-
foundVersion = pluginInfo.LatestRelease
146-
} else {
147-
versions := make(semver.Collection, 0)
148-
for v := range pluginInfo.Versions {
149-
pv, err := semver.NewVersion(v)
150-
if err != nil {
151-
return "", err
152-
}
153-
versions = append(versions, pv)
154-
}
155-
sort.Sort(sort.Reverse(versions))
156-
for _, v := range versions {
157-
if cons.Check(v) {
158-
foundVersion = v.String()
159-
break
160-
}
161-
}
162-
}
163-
164-
if foundVersion == "" {
165-
return "", errors.New("version not found")
166-
}
167-
168-
releaseAsset := pluginInfo.Versions[foundVersion].getMatchingAsset()
169-
if releaseAsset == nil {
170-
return "", fmt.Errorf("a matching plugin was not found for %s/%s", runtime.GOOS, runtime.GOARCH)
171-
}
172-
173-
targetPath := path.Join(pth, foundVersion, releaseAsset.FileName)
174-
175-
req, err := grab.NewRequest(targetPath, releaseAsset.URL)
176-
if err != nil {
177-
return "", err
178-
}
179-
if releaseAsset.Checksum != "" {
180-
sum, err := hex.DecodeString(releaseAsset.Checksum)
181-
if err != nil {
182-
return "", err
183-
}
184-
req.SetChecksum(sha256.New(), sum, true)
185-
}
186-
187-
res := grab.DefaultClient.Do(req)
188-
if d.config.ShowProgress {
189-
showDownloadProgressBar(name, res)
190-
}
191-
if err := res.Err(); err != nil {
192-
return "", err
193-
}
194-
if err := os.Chmod(res.Filename, 0755); err != nil {
195-
return "", err
196-
}
197-
198-
return res.Filename, nil
199-
}
200-
201-
func getMatchingVersionDir(pth string, cons *semver.Constraints) (string, error) {
202-
vDirs, err := ioutil.ReadDir(pth)
203-
if err != nil {
204-
return "", err
205-
}
206-
foundVers := make(semver.Collection, 0)
207-
for _, f := range vDirs {
208-
if f.IsDir() {
209-
fVer, err := semver.NewVersion(f.Name())
210-
if err != nil {
211-
continue
212-
}
213-
foundVers = append(foundVers, fVer)
214-
}
215-
}
216-
217-
if len(foundVers) == 0 {
218-
return "", errors.New("no installed version found")
219-
}
220-
sort.Sort(sort.Reverse(foundVers))
221-
222-
if cons == nil {
223-
return path.Join(pth, foundVers[0].String()), nil
224-
}
225-
226-
for _, v := range foundVers {
227-
if cons.Check(v) {
228-
return path.Join(pth, v.String()), nil
229-
}
230-
}
231-
return "", errors.New("no matching version found")
232-
}
233-
234-
func (d *Discovery) findPluginLocally(pth string, cons *semver.Constraints) (string, error) {
235-
vPth, err := getMatchingVersionDir(pth, cons)
236-
if err != nil {
237-
return "", err
238-
}
239-
240-
files, err := ioutil.ReadDir(vPth)
241-
if err != nil {
242-
return "", err
243-
}
244-
if len(files) == 0 {
245-
return "", errors.New("no plugins found")
246-
}
247-
for _, f := range files {
248-
if f.IsDir() {
249-
continue
250-
}
251-
if f.Mode()&0100 == 0 {
252-
continue
253-
}
254-
return path.Join(vPth, f.Name()), nil
255-
}
256-
return "", errors.New("no matching plugin found")
257-
}
258-
25927
func getPluginType(t string) string {
26028
switch t {
26129
case analyzer.CommitAnalyzerPluginName:
@@ -296,9 +64,9 @@ func (d *Discovery) FindPlugin(t, name string) (*plugin.PluginOpts, error) {
29664
return nil, err
29765
}
29866

299-
binPath, err := d.findPluginLocally(pPath, cons)
67+
binPath, err := findPluginLocally(pPath, cons)
30068
if err != nil {
301-
binPath, err = d.fetchPlugin(pName, pPath, cons)
69+
binPath, err = fetchPlugin(pName, pPath, cons, d.config.ShowProgress)
30270
if err != nil {
30371
return nil, err
30472
}

0 commit comments

Comments
 (0)