cmd/releaseschedule: create
Add a program that generates the release schedule diagram used on the
release schedule wiki.
For golang/go#58820
Change-Id: I8117e28704ecad2da016bcd5b0f34cb198d0e440
Reviewed-on: https://go-review.googlesource.com/c/build/+/474675
Reviewed-by: Carlos Amedee <carlos@golang.org>
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Heschi Kreinick <heschi@google.com>
diff --git a/cmd/releaseschedule/main.go b/cmd/releaseschedule/main.go
new file mode 100644
index 0000000..fbf420f
--- /dev/null
+++ b/cmd/releaseschedule/main.go
@@ -0,0 +1,109 @@
+package main
+
+import (
+ "fmt"
+ "math"
+ "os"
+ "strings"
+
+ svg "github.com/ajstarks/svgo"
+)
+
+func main() {
+ if err := doMain(); err != nil {
+ panic(err)
+ }
+}
+
+func doMain() error {
+ f, err := os.OpenFile("release.svg", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ canvas := svg.New(f)
+ canvas.Start(600, 400)
+ canvas.Translate(300, 200)
+ for i, month := range strings.Split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", " ") {
+ angle := func(midx int) float64 {
+ return (float64(midx) - 3) * 2 * math.Pi / 12
+ }
+ begin, end := angle(i), angle(i+1)
+
+ // Draw a single black wedge of the calendar.
+ path := fmt.Sprintf("M 0,0 L %v,%v A 100,100 0 0 0 %v,%v L 0 0",
+ 100*math.Sin(begin), 100*math.Cos(begin), 100*math.Sin(end), 100*math.Cos(end))
+ canvas.Path(path, "stroke: black; fill:none")
+
+ // Draw the text. Spin it around for readability in the second half.
+ canvas.RotateTranslate(50, 0, angle(i)*360/(2*math.Pi)+20)
+ if i < 6 {
+ canvas.Text(0, 0, month)
+ } else {
+ canvas.Group(`transform="rotate(180)"`, `transform-origin="13 -3"`)
+ canvas.Text(0, 0, month)
+ canvas.Gend()
+ }
+ canvas.Gend()
+ }
+
+ type milestone struct {
+ month, week int
+ name string
+ }
+ milestones := []milestone{
+ {1, 1, "Planning"},
+ {1, 3, "General development"},
+ {5, 4, "Freeze"},
+ {6, 2, "First RC"},
+ {8, 2, "Release"},
+ }
+ for relIdx, relName := range []string{"Summer", "Winter"} {
+ angle := func(m milestone) float64 {
+ return (float64(m.month-1) - 3 + (float64(m.week)-0.5)/4) * 2 * math.Pi / 12
+ }
+
+ // Shift the milestones 6 months for the winter release.
+ milestones := milestones
+ for i := range milestones {
+ milestones[i].month = (milestones[i].month + 6*relIdx) % 12
+ }
+
+ frozen := false
+ for i, m := range milestones {
+ x, y := math.Cos(angle(m)), math.Sin(angle(m))
+ // Align the text away from the center of the circle.
+ textAnchor := "start"
+ if x < 0 {
+ textAnchor = "end"
+ }
+ // Color the arc depending on the freeze state.
+ if m.name == "Freeze" {
+ frozen = true
+ }
+ color := "green"
+ if frozen {
+ color = "blue"
+ }
+
+ // Center radius of the release arc.
+ arcRadius := float64(120 + 20*relIdx)
+ // Length of the line to the label. Vary a bit to avoid text overlap.
+ lineLength := float64(30 + 5*((i+1)%2))
+ // Distance from the end of the line to the text.
+ textoff := float64(10)
+
+ // Draw the arc to the next milestone.
+ if i+1 < len(milestones) {
+ nx, ny := math.Cos(angle(milestones[i+1])), math.Sin(angle(milestones[i+1]))
+ canvas.Arc(int(x*arcRadius), int(y*arcRadius), int(arcRadius), int(arcRadius), 0, false, true, int(nx*arcRadius), int(ny*arcRadius), "stroke-width:10; fill:none; stroke: "+color)
+ }
+ // Draw the line from the inner edge of the arc.
+ canvas.Line(int(x*(arcRadius-5)), int(y*(arcRadius-5)), int(x*(arcRadius+lineLength)), int(y*(arcRadius+lineLength)), "stroke:black")
+ canvas.Text(int(x*(arcRadius+lineLength+textoff)), int(y*(arcRadius+lineLength+textoff)), relName+": "+m.name, "text-anchor: "+textAnchor)
+ }
+ }
+ canvas.Gend()
+ canvas.End()
+ return f.Close()
+}
diff --git a/go.mod b/go.mod
index 06137ec..29d8367 100644
--- a/go.mod
+++ b/go.mod
@@ -13,6 +13,7 @@
contrib.go.opencensus.io/exporter/stackdriver v0.13.5
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf
github.com/NYTimes/gziphandler v1.1.1
+ github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527
github.com/aws/aws-sdk-go v1.30.15
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625
github.com/creack/pty v1.1.18
@@ -73,7 +74,6 @@
cloud.google.com/go/monitoring v1.4.0 // indirect
cloud.google.com/go/trace v1.2.0 // indirect
github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794 // indirect
- github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
diff --git a/go.sum b/go.sum
index dd02309..2643b29 100644
--- a/go.sum
+++ b/go.sum
@@ -1028,8 +1028,6 @@
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/perf v0.0.0-20220913151710-7c6e287988f3 h1:ChUtQhjSq/uYjerTlcpLrOkD2bGMcrRuDutZVPHo3WE=
-golang.org/x/perf v0.0.0-20220913151710-7c6e287988f3/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc=
golang.org/x/perf v0.0.0-20221222170352-3fd27c239283 h1:MTXrvYGLsaCdRXRtex0LY6RotT5TXmQ3Ru+5d1CnPIM=
golang.org/x/perf v0.0.0-20221222170352-3fd27c239283/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=