mirror of https://github.com/docker/docs.git
144 lines
3.6 KiB
Go
144 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/go-openapi/runtime"
|
|
"github.com/go-openapi/strfmt"
|
|
netlify "github.com/netlify/open-api/go/models"
|
|
"github.com/netlify/open-api/go/plumbing/operations"
|
|
"github.com/netlify/open-api/go/porcelain"
|
|
netlifyctx "github.com/netlify/open-api/go/porcelain/context"
|
|
)
|
|
|
|
type NetlifyCmd struct {
|
|
Remove NetlifyRemoveCmd `kong:"cmd,name=remove"`
|
|
Deploy NetlifyDeployCmd `kong:"cmd,name=deploy"`
|
|
}
|
|
|
|
type netlifyGlobalFlags struct {
|
|
SiteName string `kong:"name='site-name',env='NETLIFY_SITE_NAME'"`
|
|
}
|
|
|
|
type NetlifyRemoveCmd struct {
|
|
netlifyGlobalFlags
|
|
}
|
|
|
|
func (s *NetlifyRemoveCmd) Run() error {
|
|
siteName := cleanSiteName(s.SiteName)
|
|
c := newNetlifyClient(getEnvOrSecret("NETLIFY_AUTH_TOKEN"))
|
|
site, err := c.getSite(siteName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get site %q: %w", siteName, err)
|
|
}
|
|
if site == nil {
|
|
log.Printf("INFO: site %s already removed", siteName)
|
|
return nil
|
|
}
|
|
return c.DeleteSite(c.ctx, site.ID)
|
|
}
|
|
|
|
type NetlifyDeployCmd struct {
|
|
netlifyGlobalFlags
|
|
PublishDir string `kong:"name='publish-dir',env='NETLIFY_PUBLISH_DIR'"`
|
|
}
|
|
|
|
func (s *NetlifyDeployCmd) Run() error {
|
|
if ok, err := isDirEmpty(s.PublishDir); err != nil {
|
|
return fmt.Errorf("cannot read publish dir %q: %w", s.PublishDir, err)
|
|
} else if !ok {
|
|
return fmt.Errorf("publish dir %q empty", s.PublishDir)
|
|
}
|
|
|
|
siteName := cleanSiteName(s.SiteName)
|
|
c := newNetlifyClient(getEnvOrSecret("NETLIFY_AUTH_TOKEN"))
|
|
|
|
site, err := c.CreateSite(c.ctx, &netlify.SiteSetup{
|
|
Site: netlify.Site{
|
|
AccountSlug: getEnvOrSecret("NETLIFY_ACCOUNT_SLUG"),
|
|
Name: siteName,
|
|
},
|
|
}, false)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create site %q: %w", siteName, err)
|
|
}
|
|
|
|
deploy, err := c.DeploySite(c.ctx, porcelain.DeployOptions{
|
|
SiteID: site.ID,
|
|
Dir: s.PublishDir,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to deploy site %q (%s): %w", siteName, site.ID, err)
|
|
}
|
|
|
|
log.Printf("INFO: site %q (%s) deployed at %s\n", siteName, site.ID, deploy.URL)
|
|
return nil
|
|
}
|
|
|
|
type netlifyClient struct {
|
|
ctx netlifyctx.Context
|
|
*porcelain.Netlify
|
|
}
|
|
|
|
func newNetlifyClient(authToken string) *netlifyClient {
|
|
return &netlifyClient{
|
|
ctx: netlifyctx.WithAuthInfo(context.Background(), authInfo(authToken)),
|
|
Netlify: porcelain.NewRetryableHTTPClient(strfmt.Default, 5),
|
|
}
|
|
}
|
|
|
|
func (c *netlifyClient) getSite(siteName string) (*netlify.Site, error) {
|
|
sites, err := c.ListSites(c.ctx, &operations.ListSitesParams{
|
|
Context: c.ctx,
|
|
Name: &siteName,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, site := range sites {
|
|
if site.Name == siteName {
|
|
return site, nil
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func authInfo(authToken string) runtime.ClientAuthInfoWriter {
|
|
return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
|
|
err := r.SetHeaderParam("User-Agent", "User-Agent: releaser/"+version)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to set useragent header: %w", err)
|
|
}
|
|
err = r.SetHeaderParam("Authorization", "Bearer "+authToken)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to set authorization header: %w", err)
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func cleanSiteName(siteName string) string {
|
|
siteName = regexp.MustCompile(`[^a-zA-Z0-9]+`).ReplaceAllString(siteName, "-")
|
|
siteName = regexp.MustCompile(`^-+\|-+$`).ReplaceAllString(siteName, "")
|
|
return strings.ToLower(strings.TrimSuffix(siteName, "-"))
|
|
}
|
|
|
|
func isDirEmpty(name string) (bool, error) {
|
|
f, err := os.Open(name)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
defer f.Close()
|
|
_, err = f.Readdirnames(1)
|
|
if err == io.EOF {
|
|
return true, nil
|
|
}
|
|
return false, err
|
|
}
|