Skip to content

Commit 34fe816

Browse files
authored
feat(internal/automation): refactor publish-release command (#2814)
Add `publish-release` command in automation package so we can auto generate documentation. For #2416
1 parent 57d2581 commit 34fe816

File tree

9 files changed

+235
-2
lines changed

9 files changed

+235
-2
lines changed

cmd/automation/doc.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,19 @@ Usage:
2525
librarian <command> [arguments]
2626
2727
The commands are:
28+
29+
# publish-release
30+
31+
The publish-release command runs a Cloud Build job to create a tag on a merged release pull
32+
request.
33+
34+
Usage:
35+
36+
automation publish-release [flags]
37+
38+
Flags:
39+
40+
-project string
41+
Google Cloud Platform project ID (default "cloud-sdk-librarian-prod")
2842
*/
2943
package main

internal/automation/automation.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package automation
16+
17+
import (
18+
"context"
19+
20+
"github.com/googleapis/librarian/internal/cli"
21+
)
22+
23+
func newAutomationCommand() *cli.Command {
24+
cmd := &cli.Command{
25+
Short: "automation manages Cloud Build resources to run Librarian CLI.",
26+
UsageLine: "automation <command> [arguments]",
27+
Long: "Automation manages Cloud Build resources to run Librarian CLI.",
28+
Commands: []*cli.Command{
29+
newCmdPublishRelease(),
30+
},
31+
}
32+
33+
cmd.Init()
34+
return cmd
35+
}
36+
37+
func newCmdPublishRelease() *cli.Command {
38+
cmdPublishRelease := &cli.Command{
39+
Short: "publish-release",
40+
UsageLine: "automation publish-release [flags]",
41+
Long: publishLongHelp,
42+
Action: func(ctx context.Context, cmd *cli.Command) error {
43+
runner := newPublishRunner(cmd.Config)
44+
return runner.run(ctx)
45+
},
46+
}
47+
48+
cmdPublishRelease.Init()
49+
addFlagProject(cmdPublishRelease.Flags, cmdPublishRelease.Config)
50+
51+
return cmdPublishRelease
52+
}

internal/automation/cli.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ var runCommandFn = RunCommand
2727

2828
// Run parses the command line arguments and triggers the specified command.
2929
func Run(ctx context.Context, args []string) error {
30+
if len(args) == 0 || args[0] == publishCmdName {
31+
cmd := newAutomationCommand()
32+
return cmd.Run(ctx, args)
33+
}
34+
3035
options, err := parseFlags(args)
3136
if err != nil {
3237
slog.Error("error parsing command", slog.Any("err", err))

internal/automation/flags.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package automation
16+
17+
import (
18+
"flag"
19+
20+
"github.com/googleapis/librarian/internal/config"
21+
)
22+
23+
func addFlagProject(fs *flag.FlagSet, cfg *config.Config) {
24+
fs.StringVar(&cfg.Project, "project", "cloud-sdk-librarian-prod", `Google Cloud Platform project ID`)
25+
}

internal/automation/help.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package automation
16+
17+
const (
18+
publishLongHelp = `The publish-release command runs a Cloud Build job to create a tag on a merged release pull
19+
request.`
20+
)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package automation
16+
17+
import (
18+
"context"
19+
20+
"github.com/googleapis/librarian/internal/config"
21+
)
22+
23+
const (
24+
publishCmdName = "publish-release"
25+
)
26+
27+
type publishRunner struct {
28+
projectID string
29+
push bool
30+
}
31+
32+
func newPublishRunner(cfg *config.Config) *publishRunner {
33+
return &publishRunner{
34+
projectID: cfg.Project,
35+
}
36+
}
37+
38+
func (r *publishRunner) run(ctx context.Context) error {
39+
return runCommandFn(ctx, publishCmdName, r.projectID, r.push, false)
40+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package automation
16+
17+
import (
18+
"context"
19+
"errors"
20+
"testing"
21+
22+
"github.com/googleapis/librarian/internal/config"
23+
)
24+
25+
func TestNewPublishRunner(t *testing.T) {
26+
t.Parallel()
27+
for _, test := range []struct {
28+
name string
29+
cfg *config.Config
30+
}{
31+
{
32+
name: "create_a_runner",
33+
cfg: &config.Config{
34+
Project: "example-project",
35+
},
36+
},
37+
} {
38+
t.Run(test.name, func(t *testing.T) {
39+
t.Parallel()
40+
runner := newPublishRunner(test.cfg)
41+
if runner.projectID != test.cfg.Project {
42+
t.Errorf("newPublishRunner() projectID is not set")
43+
}
44+
})
45+
}
46+
}
47+
48+
func TestPublishRunnerRun(t *testing.T) {
49+
t.Parallel()
50+
tests := []struct {
51+
name string
52+
args []string
53+
runCommandErr error
54+
wantErr bool
55+
}{
56+
{
57+
name: "error from RunCommand",
58+
runCommandErr: errors.New("run command failed"),
59+
wantErr: true,
60+
},
61+
}
62+
for _, test := range tests {
63+
t.Run(test.name, func(t *testing.T) {
64+
t.Parallel()
65+
runCommandFn = func(ctx context.Context, command string, projectId string, push bool, build bool) error {
66+
return test.runCommandErr
67+
}
68+
runner := &publishRunner{}
69+
if err := runner.run(t.Context()); (err != nil) != test.wantErr {
70+
t.Errorf("run() error = %v, wantErr %v", err, test.wantErr)
71+
}
72+
})
73+
}
74+
}

internal/automation/repositories.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (c *RepositoryConfig) GitURL() (string, error) {
5858
return c.FullName, nil
5959
}
6060

61-
// Validate checks the the RepositoryConfig is valid.
61+
// Validate checks the RepositoryConfig is valid.
6262
func (c *RepositoryConfig) Validate() error {
6363
if c.FullName == "" && c.Name == "" {
6464
return fmt.Errorf("name or full name is required")
@@ -77,7 +77,7 @@ func (c *RepositoryConfig) Validate() error {
7777
return nil
7878
}
7979

80-
// Validate checks the the RepositoriesConfig is valid.
80+
// Validate checks the RepositoriesConfig is valid.
8181
func (c *RepositoriesConfig) Validate() error {
8282
for i, r := range c.Repositories {
8383
err := r.Validate()

internal/config/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ type Config struct {
194194
// Requires the --library flag to be specified.
195195
LibraryVersion string
196196

197+
// Project is the ID of the Google Cloud project to use.
198+
Project string
199+
197200
// PullRequest to target and operate one in the context of a release.
198201
//
199202
// The pull request should be in the format `https://github.com/{owner}/{repo}/pull/{number}`.

0 commit comments

Comments
 (0)