Skip to content
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

0.9.0 #81

Closed
wants to merge 9 commits into from
Closed
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
69 changes: 48 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ on:
paths-ignore:
- 'README.md'
- '.github/**'
- '.dockerignore'
- '.gitignore'
- 'demo**'
- 'go.mod'
- 'go.sum'
- '.goreleaser.yaml'
branches:
- main
env:
VERSION_NUMBER: 'v0.8.0'
REGISTRY_NAME: digitalghostdev/poke-cli
VERSION_NUMBER: 'v0.9.0'
DOCKERHUB_REGISTRY_NAME: 'digitalghostdev/poke-cli'
AWS_REGION: 'us-west-2'

jobs:
snyk:
gosec:
runs-on: ubuntu-22.04

permissions:
Expand All @@ -38,23 +41,20 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Run Snyk
uses: snyk/actions/golang@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Run Gosec Security Scanner
uses: securego/gosec@master
with:
args: --sarif-file-output=snyk.sarif --skip-unresolved=true
args: '-no-fail -fmt sarif -out results.sarif ./...'

- name: Upload Result to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v2
- name: Upload SARIF Report
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: snyk.sarif
sarif_file: results.sarif

build-docker-image:
runs-on: ubuntu-22.04
needs: [snyk]
if: needs.snyk.result == 'success'
needs: [gosec]
if: needs.gosec.result == 'success'

steps:
- name: Checkout
Expand All @@ -81,6 +81,33 @@ jobs:
name: poke-cli
path: /tmp/poke-cli.tar

# Uploading to Elastic Container Registry has a backup method.
upload-to-ecr:
runs-on: ubuntu-22.04
needs: [build-docker-image]
if: needs.build-docker-image.result == 'success'

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Configure AWS
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Build, tag, and push image to Amazon ECR
run : |
docker build -t poke-cli:${{ env.VERSION_NUMBER }} .
docker tag poke-cli:${{ env.VERSION_NUMBER }} ${{ secrets.AWS_ECR_NAME }}:${{ env.VERSION_NUMBER }}
docker push ${{ secrets.AWS_ECR_NAME }}:${{ env.VERSION_NUMBER }}

syft:
permissions:
contents: 'read'
Expand Down Expand Up @@ -150,8 +177,8 @@ jobs:

architecture-build:
runs-on: ubuntu-22.04
needs: [snyk]
if: needs.snyk.result == 'success'
needs: [gosec]
if: needs.gosec.result == 'success'

strategy:
fail-fast: false
Expand All @@ -166,7 +193,7 @@ jobs:
id: meta
uses: 'docker/[email protected]'
with:
images: ${{ env.REGISTRY_NAME }}
images: ${{ env.DOCKERHUB_REGISTRY_NAME }}

- name: Set up QEMU
uses: 'docker/setup-qemu-action@v3'
Expand All @@ -187,7 +214,7 @@ jobs:
context: .
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY_NAME }},push-by-digest=true,name-canonical=true,push=true
outputs: type=image,name=${{ env.DOCKERHUB_REGISTRY_NAME }},push-by-digest=true,name-canonical=true,push=true

- name: Export Digest
run: |
Expand Down Expand Up @@ -232,7 +259,7 @@ jobs:
id: meta
uses: 'docker/[email protected]'
with:
images: ${{ env.REGISTRY_NAME }}
images: ${{ env.DOCKERHUB_REGISTRY_NAME }}
tags: ${{ env.VERSION_NUMBER }}

- name: Login to Docker Hub
Expand All @@ -245,8 +272,8 @@ jobs:
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY_NAME }}@sha256:%s ' *)
$(printf '${{ env.DOCKERHUB_REGISTRY_NAME }}@sha256:%s ' *)

- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_NAME }}:${{ steps.meta.outputs.version }}
docker buildx imagetools inspect ${{ env.DOCKERHUB_REGISTRY_NAME }}:${{ steps.meta.outputs.version }}
2 changes: 2 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ builds:
- linux
- windows
- darwin
ldflags:
- -s -w -X main.version=v0.9.0

archives:
- format: tar.gz
Expand Down
21 changes: 14 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
FROM golang:1.23-alpine3.19
# build 1
FROM golang:1.23-alpine3.19 AS build

WORKDIR /app

ENV TERM=xterm-256color
ENV COLOR_OUTPUT=true
COPY go.mod go.sum ./
RUN go mod download

COPY . .

COPY . /app
RUN go build -ldflags "-X main.version=v0.9.0" -o poke-cli .

RUN PATH="$PATH:~/go/bin:/usr/local/go/bin:$GOPATH/bin"
# build 2
FROM gcr.io/distroless/static-debian12:nonroot

RUN go install
COPY --from=build /app/poke-cli /app/poke-cli

ENV TERM=xterm-256color
ENV COLOR_OUTPUT=true

ENTRYPOINT ["poke-cli"]
ENTRYPOINT ["/app/poke-cli"]
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img height="250" width="350" src="https://cdn.simpleicons.org/pokemon/FFCC00" alt="pokemon-logo"/>
<h1>Pokémon CLI</h1>
<img src="https://img.shields.io/github/v/release/digitalghost-dev/poke-cli?style=flat-square&logo=git&logoColor=FFCC00&label=Release%20Version&labelColor=EEE&color=FFCC00" alt="version-label">
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v0.8.0?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v0.9.0?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
<img src="https://img.shields.io/github/actions/workflow/status/digitalghost-dev/poke-cli/ci.yml?branch=main&style=flat-square&logo=github&logoColor=FFCC00&label=CI&labelColor=EEE&color=FFCC00" alt="ci-status-badge">
</div>
<div align="center">
Expand All @@ -19,7 +19,7 @@ My aim is to have four commands finished for `v1.0.0`. Read more in the [Roadmap

---
## Demo
![demo](https://pokemon-objects.nyc3.digitaloceanspaces.com/demo-v0.8.0.gif)
![demo](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/demo.gif)

---
## Install
Expand Down Expand Up @@ -68,18 +68,17 @@ _Use a Docker Image_
* Necessary.

```bash
docker run --rm -i -t digitalghostdev/poke-cli:v0.8.0 <command> [subcommand] flag]
docker run --rm -i -t digitalghostdev/poke-cli:v0.9.0 <command> [subcommand] flag]
```

### Go Install
_Install the executable yourself_
_If you have Go already, install the executable yourself_

1. Install [Golang](https://go.dev/dl/).
2. Once installed, run the following command:
1. Run the following command:
```bash
go install github.com/digitalghost-dev/poke-cli@v0
```
3. The tool is ready to use!
2. The tool is ready to use!
---
## Usage
By running `poke-cli [-h | --help]`, it'll display information on how to use the tool.
Expand Down
41 changes: 37 additions & 4 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/digitalghost-dev/poke-cli/cmd"
"github.com/digitalghost-dev/poke-cli/flags"
"os"
"runtime/debug"
)

var (
Expand All @@ -20,10 +21,39 @@ var (
BorderForeground(lipgloss.Color("#F2055C"))
)

var version = "(devel)"

func currentVersion() {
if version != "(devel)" {
// Use version injected by -ldflags
fmt.Printf("Version: %s\n", version)
return
}

// Fallback to build info when version is not set
buildInfo, ok := debug.ReadBuildInfo()
if !ok {
fmt.Println("Version: unknown (unable to read build info)")
return
}

if buildInfo.Main.Version != "" {
fmt.Printf("Version: %s\n", buildInfo.Main.Version)
} else {
fmt.Println("Version: (devel)")
}
}

func runCLI(args []string) int {
mainFlagSet := flag.NewFlagSet("poke-cli", flag.ContinueOnError)
latestFlag := mainFlagSet.Bool("latest", false, "Prints the program's latest Docker Image and Release versions.")
shortLatestFlag := mainFlagSet.Bool("l", false, "Prints the program's latest Docker Image and Release versions.")

// -l, --latest flag retrieves the latest Docker image and GitHub release versions available
latestFlag := mainFlagSet.Bool("latest", false, "Prints the program's latest Docker image and release versions.")
shortLatestFlag := mainFlagSet.Bool("l", false, "Prints the program's latest Docker image and release versions.")

// -v, --version flag retrives the currently installed version
currentVersionFlag := mainFlagSet.Bool("version", false, "Prints the current version")
shortCurrentVersionFlag := mainFlagSet.Bool("v", false, "Prints the current version")

mainFlagSet.Usage = func() {
helpMessage := helpBorder.Render(
Expand All @@ -34,8 +64,8 @@ func runCLI(args []string) int {
fmt.Sprintf("\n\t%-15s %s", "poke-cli <command> <subcommand> [flag]", ""),
"\n\n", styleBold.Render("FLAGS:"),
fmt.Sprintf("\n\t%-15s %s", "-h, --help", "Shows the help menu"),
fmt.Sprintf("\n\t%-15s %s", "-l, --latest", "Prints the latest available"),
fmt.Sprintf("\n\t%-15s %s", "", "version of the program"),
fmt.Sprintf("\n\t%-15s %s", "-l, --latest", "Prints the latest version available"),
fmt.Sprintf("\n\t%-15s %s", "-v, --version", "Prints the current version"),
"\n\n", styleBold.Render("AVAILABLE COMMANDS:"),
fmt.Sprintf("\n\t%-15s %s", "pokemon", "Get details of a specific Pokémon"),
fmt.Sprintf("\n\t%-15s %s", "types", "Get details of a specific typing"),
Expand Down Expand Up @@ -70,6 +100,9 @@ func runCLI(args []string) int {
} else if *latestFlag || *shortLatestFlag {
flags.LatestFlag()
return 0
} else if *currentVersionFlag || *shortCurrentVersionFlag {
currentVersion()
return 0
} else if cmdFunc, exists := commands[os.Args[1]]; exists {
cmdFunc()
return 0
Expand Down
2 changes: 1 addition & 1 deletion cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func TestRunCLI(t *testing.T) {
{
name: "Latest Flag",
args: []string{"-l"},
expectedOutput: "Latest Docker image version: v0.7.2\nLatest release tag: v0.7.2\n",
expectedOutput: "Latest Docker image version: v0.8.0\nLatest release tag: v0.8.0\n",
expectedCode: 0,
},
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func displayTypeDetails(typesName string, endpoint string) {
selectedType := cases.Title(language.English).String(typeName)
coloredType := lipgloss.NewStyle().Foreground(lipgloss.Color(getTypeColor(typeName))).Render(selectedType)

fmt.Printf("You selected the %s type.\nNumber of Pokémon with type: %d\n", coloredType, len(typesStruct.Pokemon))
fmt.Printf("You selected the %s type.\nNumber of Pokémon with type: %d\nNumber of moves with type: %d\n", coloredType, len(typesStruct.Pokemon), len(typesStruct.Moves))
fmt.Println("----------")
fmt.Println(styleBold.Render("Damage Chart:"))

Expand Down
25 changes: 21 additions & 4 deletions connections/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package connections

import (
"encoding/json"
"errors"
"flag"
"fmt"
"github.com/charmbracelet/lipgloss"
"io"
"net/http"
"net/url"
"os"
)

Expand Down Expand Up @@ -39,8 +41,12 @@ type PokemonJSONStruct struct {
}

type TypesJSONStruct struct {
Name string `json:"name"`
ID int `json:"id"`
Name string `json:"name"`
ID int `json:"id"`
Moves []struct {
Name string `json:"name"`
URL string `json:"url"`
} `json:"moves"`
Pokemon []struct {
Pokemon struct {
Name string `json:"name"`
Expand Down Expand Up @@ -80,8 +86,19 @@ var red = lipgloss.Color("#F2055C")
var errorColor = lipgloss.NewStyle().Foreground(red)

// ApiCallSetup Helper function to handle API calls and JSON unmarshalling
func ApiCallSetup(url string, target interface{}) error {
res, err := http.Get(url)
func ApiCallSetup(rawURL string, target interface{}) error {
// Parse and validate the URL
parsedURL, err := url.Parse(rawURL)
if err != nil {
return fmt.Errorf("invalid URL provided: %w", err)
}

// Check the scheme to ensure it's HTTPS
if parsedURL.Scheme != "https" {
return errors.New("only HTTPS URLs are allowed for security reasons")
}

res, err := http.Get(parsedURL.String())
if err != nil {
return fmt.Errorf("error making GET request: %w", err)
}
Expand Down
21 changes: 20 additions & 1 deletion flags/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os/exec"
)

Expand All @@ -24,7 +25,25 @@ func latestRelease(githubAPIURL string) {
TagName string `json:"tag_name"`
}

response, err := http.Get(githubAPIURL)
// Parse and validate the URL
parsedURL, err := url.Parse(githubAPIURL)
if err != nil {
fmt.Println("Invalid URL:", err)
return
}

// Enforce HTTPS and a specific host (e.g., api.github.com)
if parsedURL.Scheme != "https" {
fmt.Println("Only HTTPS URLs are allowed for security reasons")
return
}
if parsedURL.Host != "api.github.com" {
fmt.Println("URL host is not allowed")
return
}

// Make the HTTP GET request
response, err := http.Get(parsedURL.String())
if err != nil {
fmt.Println("Error fetching data:", err)
return
Expand Down
Loading