Skip to content

feat: wire announcement api (backport #4615) #4620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

## Features

- [#4615](https://github.com/ignite/cli/pull/4615) Fetch Ignite announcements from API.

## Changes

- [#4586](https://github.com/ignite/cli/pull/4586) Remove network as default plugin.
Expand Down
2 changes: 1 addition & 1 deletion ignite/cmd/bubblemodel/chain_serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ func (m ChainServe) renderQuitView() string {
}

fmt.Fprintf(&view, "%s %s\n", icons.Info, colors.Info("Stopped"))
view.WriteString(announcements.GetAnnouncements())
view.WriteString(announcements.Fetch())

return view.String()
}
Expand Down
11 changes: 8 additions & 3 deletions ignite/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ignitecmd

import (
"context"
"fmt"
"os"
"path/filepath"
"slices"
Expand All @@ -12,6 +13,7 @@ import (
flag "github.com/spf13/pflag"

"github.com/ignite/cli/v28/ignite/config"
"github.com/ignite/cli/v28/ignite/pkg/announcements"
"github.com/ignite/cli/v28/ignite/pkg/cache"
"github.com/ignite/cli/v28/ignite/pkg/cliui"
uilog "github.com/ignite/cli/v28/ignite/pkg/cliui/log"
Expand Down Expand Up @@ -49,14 +51,17 @@ func New(ctx context.Context) (*cobra.Command, func(), error) {
c := &cobra.Command{
Use: "ignite",
Short: "Ignite CLI offers everything you need to scaffold, test, build, and launch your blockchain",
Long: `Ignite CLI is a tool for creating sovereign blockchains built with Cosmos SDK, the world's
Long: fmt.Sprintf(`Ignite CLI is a tool for creating sovereign blockchains built with Cosmos SDK, the world's
most popular modular blockchain framework. Ignite CLI offers everything you need to scaffold,
test, build, and launch your blockchain.

To get started, create a blockchain:

ignite scaffold chain example
`,
$ ignite scaffold chain example

Announcements:
%s
`, announcements.Fetch()),
SilenceUsage: true,
SilenceErrors: true,
Args: cobra.MinimumNArgs(0), // note(@julienrbrt): without this, ignite __complete(noDesc) hidden commands are not working.
Expand Down
26 changes: 17 additions & 9 deletions ignite/pkg/announcements/announcement.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,49 @@ import (
"fmt"
"net/http"
"strings"
"time"

"github.com/ignite/cli/v28/ignite/pkg/cliui/icons"
)

var (
SurveyLink = "https://bit.ly/3WZS2uS"
AnnouncementAPI = "http://api.ignite.com/announcements"
SurveyLink = "https://bit.ly/3WZS2uS"
APIURL = "http://announcements.ignite.com/v1/announcements"
)

type api struct {
Announcements []announcement `json:"announcements"`
}

type announcement struct {
Announcements []string `json:"announcements"`
ID string `json:"id"`
Text string `json:"text"`
Timestamp time.Time `json:"timestamp"`
User string `json:"user"`
}

func GetAnnouncements() string {
resp, err := http.Get(AnnouncementAPI) //nolint:gosec
// Fetch fetches the latest announcements from the API.
func Fetch() string {
resp, err := http.Get(APIURL) //nolint:gosec
if err != nil || resp.StatusCode != 200 {
return fallbackData()
}
defer resp.Body.Close()

var data announcement
var data api
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return fallbackData()
}

// is this needed? or if its empty we don't want to show anything?
if len(data.Announcements) == 0 {
return fallbackData()
}

var out strings.Builder
fmt.Fprintf(&out, "\n%s %s\n", icons.Announcement, "Announcements")

for _, announcement := range data.Announcements {
fmt.Fprintf(&out, "%s %s\n", icons.Bullet, announcement)
for _, msg := range data.Announcements {
fmt.Fprintf(&out, "%s %s\n", icons.Bullet, msg.Text)
}

return out.String()
Expand Down
14 changes: 7 additions & 7 deletions ignite/pkg/announcements/announcement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/ignite/cli/v28/ignite/pkg/announcements"
)

func TestGetAnnouncements(t *testing.T) {
func TestFetchAnnouncements(t *testing.T) {
fallbackData := fmt.Sprintf("\n💬 Survey: %s\n", announcements.SurveyLink)

tests := []struct {
Expand All @@ -20,9 +20,9 @@ func TestGetAnnouncements(t *testing.T) {
}{
{
name: "successful retrieval",
mockResponse: `{"announcements":["Announcement 1","Announcement 2"]}`,
mockResponse: `{"version":1,"announcements":[{"id":"1744230503810","text":"New Ignite announcement: v1.0.0 released!","timestamp":"2025-04-09T20:28:23.810Z","user":"announcement-bot"}]}`,
statusCode: http.StatusOK,
expected: "\n🗣️ Announcements\n⋆ Announcement 1\n⋆ Announcement 2\n",
expected: "\n🗣️ Announcements\n⋆ New Ignite announcement: v1.0.0 released!\n",
},
{
name: "empty announcements",
Expand Down Expand Up @@ -52,11 +52,11 @@ func TestGetAnnouncements(t *testing.T) {
}))
defer server.Close()

originalAPI := announcements.AnnouncementAPI
announcements.AnnouncementAPI = server.URL
defer func() { announcements.AnnouncementAPI = originalAPI }()
originalAPI := announcements.APIURL
announcements.APIURL = server.URL
defer func() { announcements.APIURL = originalAPI }()

result := announcements.GetAnnouncements()
result := announcements.Fetch()
if result != tt.expected {
t.Errorf("expected %q, got %q", tt.expected, result)
}
Expand Down
Loading