diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 28ed9fd..efa0658 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -25,17 +25,20 @@ jobs: go-version: 1.16 - name: Generate plan.yml run: >- - ./build-emacs-for-macos --plan --plan-file=plan.yml + go run ./cmd/github-release --plan plan.yml plan ${{ github.event.inputs.gitRef }} - - name: Phow plan - run: cat plan.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Show plan + run: >- + cat plan.yml - name: Check if release and asset already exist for given plan id: check continue-on-error: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: >- go run ./cmd/github-release --plan plan.yml check + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Install dependencies if: steps.check.outcome == 'failure' run: >- @@ -46,8 +49,8 @@ jobs: ./build-emacs-for-macos --plan-file=plan.yml - name: Publish release if: steps.check.outcome == 'failure' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: >- go run ./cmd/github-release --plan plan.yml publish --prerelease=${{ github.event.inputs.prerelease }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/build-emacs-for-macos b/build-emacs-for-macos index 1351c25..e8bbbec 100755 --- a/build-emacs-for-macos +++ b/build-emacs-for-macos @@ -95,6 +95,7 @@ class Build ref: given_plan['ref'], date: Date.parse(given_plan['date']) } + @archive_filename = given_plan['archive'] end unless meta[:sha] && meta[:date] @@ -102,7 +103,7 @@ class Build end if options[:plan] - plan + save_plan return end @@ -123,7 +124,7 @@ class Build private - def plan + def save_plan plan_yml = YAML.dump( 'ref' => meta[:ref], 'sha' => meta[:sha], @@ -399,24 +400,28 @@ class Build OS.arch ].compact - @archive_filename = "Emacs.app-[#{metadata.join('][')}].tbz" + filename = "Emacs.app-[#{metadata.join('][')}].tbz" + @archive_filename = File.join(builds_dir, filename) end def archive_app(app) - FileUtils.mkdir_p(builds_dir) + filename = File.basename(archive_filename) + target_dir = File.dirname(archive_filename) + relative_target_dir = target_dir.gsub(root_dir + '/', '') - filename = archive_filename - target = File.join(builds_dir, filename) + FileUtils.mkdir_p(target_dir) app_base = File.basename(app) app_dir = File.dirname(app) - if !File.exist?(target) - info "Creating #{filename} archive in \"#{builds_dir}\"..." - FileUtils.cd(app_dir) { system('tar', '-cjf', target, app_base) } + if !File.exist?(archive_filename) + info "Creating #{filename} archive in \"#{relative_target_dir}\"..." + FileUtils.cd(app_dir) do + system('tar', '-cjf', archive_filename, app_base) + end else info "#{filename} archive exists in " \ - "#{builds_dir.gsub(root_dir + '/', '')}, skipping archving." + "#{relative_target_dir}, skipping archving." end end diff --git a/cmd/github-release/check_cmd.go b/cmd/github-release/check_cmd.go index c5896ed..51e5f80 100644 --- a/cmd/github-release/check_cmd.go +++ b/cmd/github-release/check_cmd.go @@ -19,7 +19,11 @@ var checkCmd = &cli.Command{ func checkAction(c *cli.Context, opts *globalOptions) error { gh := opts.gh repo := opts.repo - plan := opts.plan + plan, err := LoadPlan(opts.plan) + if err != nil { + return err + } + releaseName := plan.ReleaseName() fmt.Printf( diff --git a/cmd/github-release/main.go b/cmd/github-release/main.go index 55ae8c0..f9b1f13 100644 --- a/cmd/github-release/main.go +++ b/cmd/github-release/main.go @@ -6,7 +6,6 @@ import ( "github.com/google/go-github/v35/github" "github.com/urfave/cli/v2" - "gopkg.in/yaml.v3" ) var app = &cli.App{ @@ -37,30 +36,20 @@ var app = &cli.App{ Commands: []*cli.Command{ checkCmd, publishCmd, + planCmd, }, } type globalOptions struct { gh *github.Client repo *Repo - plan *Plan + plan string } func actionHandler( f func(*cli.Context, *globalOptions) error, ) func(*cli.Context) error { return func(c *cli.Context) error { - b, err := os.ReadFile(c.Path("plan")) - if err != nil { - return err - } - - plan := &Plan{} - err = yaml.Unmarshal(b, plan) - if err != nil { - return err - } - token := c.String("github-token") if t := os.Getenv("GITHUB_TOKEN"); t != "" { token = t @@ -69,7 +58,7 @@ func actionHandler( opts := &globalOptions{ gh: NewGitHubClient(c.Context, token), repo: NewRepo(c.String("repo")), - plan: plan, + plan: c.String("plan"), } return f(c, opts) diff --git a/cmd/github-release/os_info.go b/cmd/github-release/os_info.go new file mode 100644 index 0000000..779e97e --- /dev/null +++ b/cmd/github-release/os_info.go @@ -0,0 +1,44 @@ +package main + +import ( + "os/exec" + "strings" +) + +var OSInfo = &osInfo{} + +type osInfo struct { + version string + arch string +} + +func (s *osInfo) Arch() string { + if s.arch != "" { + return s.arch + } + + cmd, err := exec.Command("uname", "-m").CombinedOutput() + if err != nil { + panic(err) + } + + s.arch = strings.TrimSpace(string(cmd)) + + return s.arch +} + +func (s *osInfo) Version() string { + if s.version != "" { + return s.version + } + + cmd, err := exec.Command("sw_vers", "-productVersion").CombinedOutput() + if err != nil { + panic(err) + } + + parts := strings.Split(string(cmd), ".") + s.version = strings.Join(parts[0:2], ".") + + return s.version +} diff --git a/cmd/github-release/plan.go b/cmd/github-release/plan.go index de7d332..6d1608d 100644 --- a/cmd/github-release/plan.go +++ b/cmd/github-release/plan.go @@ -2,9 +2,12 @@ package main import ( "fmt" + "os" "path/filepath" "regexp" "strings" + + "gopkg.in/yaml.v3" ) type Plan struct { @@ -14,6 +17,18 @@ type Plan struct { Archive string `yaml:"archive"` } +func LoadPlan(filename string) (*Plan, error) { + b, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + + plan := &Plan{} + err = yaml.Unmarshal(b, plan) + + return plan, err +} + func (s *Plan) ReleaseName() string { ref := nonAlphaNum.ReplaceAllString(s.Ref, "-") ref = regexp.MustCompile(`\.`).ReplaceAllString(ref, "-") diff --git a/cmd/github-release/plan_cmd.go b/cmd/github-release/plan_cmd.go new file mode 100644 index 0000000..c471cf9 --- /dev/null +++ b/cmd/github-release/plan_cmd.go @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/urfave/cli/v2" + "gopkg.in/yaml.v3" +) + +var planCmd = &cli.Command{ + Name: "plan", + Usage: "Plan if GitHub release and asset exists", + UsageText: "github-release [global options] plan []", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "emacs-mirror-repo", + Usage: "Github owner/repo to get Emacs commit info from", + Aliases: []string{"e"}, + EnvVars: []string{"EMACS_MIRROR_REPO"}, + Value: "emacs-mirror/emacs", + }, + }, + Action: actionHandler(planAction), +} + +func planAction(c *cli.Context, opts *globalOptions) error { + gh := opts.gh + planFile := opts.plan + emacsRepo := NewRepo(c.String("emacs-mirror-repo")) + + ref := c.Args().Get(0) + if ref == "" { + ref = "master" + } + + commit, _, err := gh.Repositories.GetCommit( + c.Context, emacsRepo.Owner, emacsRepo.Name, ref, + ) + if err != nil { + return err + } + + commitDate := commit.GetCommit().Committer.GetDate() + date := commitDate.Format("2006-01-02") + sha := commit.GetSHA() + + archive := fmt.Sprintf( + "Emacs.app-[%s][%s][%s][%s][%s].tbz", + nonAlphaNum.ReplaceAllString(ref, "-"), + date, + sha[0:7], + "macOS-"+OSInfo.Version(), + OSInfo.Arch(), + ) + + rootDir, err := os.Getwd() + if err != nil { + return err + } + buildsDir := filepath.Join(rootDir, "builds") + + plan := &Plan{ + Ref: ref, + SHA: sha, + Date: date, + Archive: filepath.Join(buildsDir, archive), + } + + b, err := yaml.Marshal(plan) + if err != nil { + return err + } + + return os.WriteFile(planFile, b, 0666) +} diff --git a/cmd/github-release/publish_cmd.go b/cmd/github-release/publish_cmd.go index 473dd0e..1d7f94d 100644 --- a/cmd/github-release/publish_cmd.go +++ b/cmd/github-release/publish_cmd.go @@ -33,7 +33,10 @@ var publishCmd = &cli.Command{ func publishAction(c *cli.Context, opts *globalOptions) error { gh := opts.gh repo := opts.repo - plan := opts.plan + plan, err := LoadPlan(opts.plan) + if err != nil { + return err + } releaseName := plan.ReleaseName() githubSHA := c.String("github-sha")