@@ -20,6 +20,7 @@ import (
2020 "fmt"
2121 "log/slog"
2222 "regexp"
23+ "slices"
2324 "strconv"
2425 "strings"
2526 "time"
@@ -33,6 +34,8 @@ import (
3334const (
3435 pullRequestSegments = 5
3536 tagAndReleaseCmdName = "tag-and-release"
37+ releasePendingLabel = "release:pending"
38+ releaseDoneLabel = "release:done"
3639)
3740
3841var (
@@ -135,22 +138,39 @@ func (r *tagAndReleaseRunner) determinePullRequestsToProcess(ctx context.Context
135138
136139 slog .Info ("searching for pull requests to tag and release" )
137140 thirtyDaysAgo := time .Now ().Add (- 30 * 24 * time .Hour ).Format (time .RFC3339 )
138- query := fmt .Sprintf ("label:release:pending merged:>=%s" , thirtyDaysAgo )
141+ query := fmt .Sprintf ("label:%s merged:>=%s" , releasePendingLabel , thirtyDaysAgo )
139142 prs , err := r .ghClient .SearchPullRequests (ctx , query )
140143 if err != nil {
141144 return nil , fmt .Errorf ("failed to search pull requests: %w" , err )
142145 }
143146 return prs , nil
144147}
145148
146- func (r * tagAndReleaseRunner ) processPullRequest (_ context.Context , p * github.PullRequest ) error {
149+ func (r * tagAndReleaseRunner ) processPullRequest (ctx context.Context , p * github.PullRequest ) error {
147150 slog .Info ("processing pull request" , "pr" , p .GetNumber ())
148- // hack to make CI happy until we impl
149- // TODO(https://github.com/googleapis/librarian/issues/1009)
150- if p . GetNumber () != 0 {
151- return fmt . Errorf ( "skipping pull request %d" , p . GetNumber ())
151+ releases := parsePullRequestBody ( p . GetBody ())
152+ if len ( releases ) == 0 {
153+ slog . Warn ( "no release details found in pull request body, skipping" )
154+ return nil
152155 }
153- return nil
156+ for _ , release := range releases {
157+ slog .Info ("creating release" , "library" , release .Library , "version" , release .Version )
158+ commitish := p .GetMergeCommitSHA ()
159+
160+ lib := r .state .LibraryByID (release .Library )
161+ if lib == nil {
162+ return fmt .Errorf ("library %s not found" , release .Library )
163+ }
164+
165+ // Create the release.
166+ tagName := formatTag (lib , release .Version )
167+ releaseName := fmt .Sprintf ("%s %s" , release .Library , release .Version )
168+ if _ , err := r .ghClient .CreateRelease (ctx , tagName , releaseName , release .Body , commitish ); err != nil {
169+ return fmt .Errorf ("failed to create release: %w" , err )
170+ }
171+
172+ }
173+ return r .replacePendingLabel (ctx , p )
154174}
155175
156176// libraryRelease holds the parsed information from a pull request body.
@@ -188,3 +208,19 @@ func parsePullRequestBody(body string) []libraryRelease {
188208
189209 return parsedBodies
190210}
211+
212+ // replacePendingLabel is a helper function that replaces the `release:pending` label with `release:done`.
213+ func (r * tagAndReleaseRunner ) replacePendingLabel (ctx context.Context , p * github.PullRequest ) error {
214+ var currentLabels []string
215+ for _ , label := range p .Labels {
216+ currentLabels = append (currentLabels , label .GetName ())
217+ }
218+ currentLabels = slices .DeleteFunc (currentLabels , func (s string ) bool {
219+ return s == releasePendingLabel
220+ })
221+ currentLabels = append (currentLabels , releaseDoneLabel )
222+ if err := r .ghClient .ReplaceLabels (ctx , p .GetNumber (), currentLabels ); err != nil {
223+ return fmt .Errorf ("failed to replace labels: %w" , err )
224+ }
225+ return nil
226+ }
0 commit comments