diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 578d575..c86a98e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,6 +16,8 @@ on:
- 'README.md'
- '.github/**'
- '.dockerignore'
+ - 'docs/**'
+ - 'etl/**'
- '.gitignore'
- 'demo**'
- 'go.mod'
@@ -26,7 +28,7 @@ on:
- main
env:
- VERSION_NUMBER: 'v1.3.2'
+ VERSION_NUMBER: 'v1.3.3'
DOCKERHUB_REGISTRY_NAME: 'digitalghostdev/poke-cli'
AWS_REGION: 'us-west-2'
@@ -53,7 +55,77 @@ jobs:
with:
sarif_file: results.sarif
- build-docker-image:
+ build-docs-docker-image:
+ runs-on: ubuntu-22.04
+ needs: [ gosec ]
+ if: needs.gosec.result == 'success'
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ sparse-checkout: |
+ docs
+
+ - name: Set up Docker Buildx
+ uses: 'docker/setup-buildx-action@v3.0.0'
+
+ - name: Prepare Docker Build Context
+ run: |
+ mkdir docker-context
+ rsync -av --exclude=docker-context . docker-context/
+
+ - name: Build and Export
+ uses: 'docker/build-push-action@v5.0.0'
+ with:
+ context: ./docker-context
+ file: ./docker-context/docs/Dockerfile
+ tags: docs:latest
+ outputs: type=docker,dest=/tmp/docs.tar
+
+ - name: Upload Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: docs
+ path: /tmp/docs.tar
+
+ upload-docs-to-ecr:
+ runs-on: ubuntu-22.04
+ needs: [build-docs-docker-image]
+ if: needs.build-docs-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: Download Artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: docs
+ path: /tmp
+
+ - name: Load Image
+ run: docker load -i /tmp/docs.tar
+
+ - name: Tag and Push
+ run: |
+ docker tag docs:latest ${{ secrets.AWS_DOCS_ECR_NAME }}:latest
+ docker push ${{ secrets.AWS_DOCS_ECR_NAME }}:latest
+
+ # AWS will then take care of updating App Runner with the latest version
+
+ build-cli-docker-image:
runs-on: ubuntu-22.04
needs: [gosec]
if: needs.gosec.result == 'success'
@@ -83,11 +155,11 @@ jobs:
name: poke-cli
path: /tmp/poke-cli.tar
- # Uploading to Elastic Container Registry has a backup method.
- upload-to-ecr:
+ # Uploading to Elastic Container Registry as a backup method.
+ upload-cli-to-ecr:
runs-on: ubuntu-22.04
- needs: [build-docker-image]
- if: needs.build-docker-image.result == 'success'
+ needs: [build-cli-docker-image]
+ if: needs.build-cli-docker-image.result == 'success'
steps:
- name: Checkout
@@ -116,8 +188,8 @@ jobs:
id-token: 'write'
runs-on: ubuntu-22.04
- needs: [build-docker-image]
- if: needs.build-docker-image.result == 'success'
+ needs: [build-cli-docker-image]
+ if: needs.build-cli-docker-image.result == 'success'
steps:
- name: Checkout
diff --git a/.gitignore b/.gitignore
index 1ef22dd..33bfbea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,4 +25,7 @@ go.work
go.work.sum
# env file
-.env
\ No newline at end of file
+.env
+
+# Python
+etl/.venv
\ No newline at end of file
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index f73112f..e137734 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -14,10 +14,10 @@ builds:
- windows
- darwin
ldflags:
- - -s -w -X main.version=v1.3.2
+ - -s -w -X main.version=v1.3.3
archives:
- - format: tar.gz
+ - formats: [ 'zip' ]
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
@@ -28,7 +28,7 @@ archives:
# use zip for windows archives
format_overrides:
- goos: windows
- format: zip
+ - formats: [ 'zip' ]
changelog:
sort: asc
@@ -37,11 +37,20 @@ changelog:
- "^docs:"
- "^test:"
-brews:
- - repository:
+homebrew_casks:
+ - name: poke-cli
+ conflicts:
+ - formula: poke-cli
+ repository:
owner: digitalghost-dev
name: homebrew-poke-cli
token: "{{.Env.GITHUB_TOKEN}}"
homepage: "https://github.com/digitalghost-dev/poke-cli"
- description: "A CLI tool written in Go that allows you to view data about Pokémon from the terminal."
+ description: "A hybrid CLI/TUI tool written in Go for viewing Pokémon data from the terminal!"
license: "Apache License 2.0"
+ hooks:
+ post:
+ install: |
+ if system_command("/usr/bin/xattr", args: ["-h"]).exit_status == 0
+ system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/poke-cli"]
+ end
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 5b30230..8263051 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,16 +1,18 @@
-# build 1
-FROM golang:1.24.4-alpine3.21 AS build
+# Stage 1: Dependencies
+FROM golang:1.24.4-alpine3.21 AS deps
WORKDIR /app
COPY go.mod go.sum ./
-RUN go mod download
+RUN go mod tidy
+# Stage 2: Build
+FROM deps AS build-stage
COPY . .
-RUN go build -ldflags "-X main.version=v1.3.2" -o poke-cli .
+RUN go build -ldflags "-X main.version=v1.3.3" -o poke-cli .
-# build 2
+# Stage 3: Production
FROM --platform=$BUILDPLATFORM alpine:latest
# Install only necessary packages and remove them after use
@@ -19,7 +21,7 @@ RUN apk add --no-cache shadow && \
sed -i 's/^root:.*/root:!*:0:0:root:\/root:\/sbin\/nologin/' /etc/passwd && \
apk del shadow
-COPY --from=build /app/poke-cli /app/poke-cli
+COPY --from=build-stage /app/poke-cli /app/poke-cli
ENV TERM=xterm-256color
ENV COLOR_OUTPUT=true
diff --git a/README.md b/README.md
index e1fc1bd..6b7a0d0 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Pokémon CLI
-
+
@@ -13,6 +13,7 @@
## Overview
`poke-cli` is a hybrid of a classic CLI and a modern TUI tool for viewing data about Pokémon! This is my first Go project.
+View the [documentation](https://docs.poke-cli.com)!
The architecture behind how the tool works is straight forward:
1. Each command indicates which [API](https://pokeapi.co/) endpoint to use.
@@ -23,7 +24,7 @@ View future plans in the [Roadmap](#roadmap) section.
---
## Demo
-
+
---
## Installation
@@ -76,11 +77,11 @@ View future plans in the [Roadmap](#roadmap) section.
3. Choose how to interact with the container:
* Run a single command and exit:
```bash
- docker run --rm -it digitalghostdev/poke-cli:v1.3.2 [subcommand] flag]
+ docker run --rm -it digitalghostdev/poke-cli:v1.3.3 [subcommand] flag]
```
* Enter the container and use its shell:
```bash
- docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.3.2 -c "cd /app && exec sh"
+ docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.3.3 -c "cd /app && exec sh"
# placed into the /app directory, run the program with './poke-cli'
# example: ./poke-cli ability swift-swim
```
diff --git a/cli.go b/cli.go
index 827a08d..9a489c0 100644
--- a/cli.go
+++ b/cli.go
@@ -74,6 +74,7 @@ func runCLI(args []string) int {
"\n\n", styling.StyleItalic.Render("hint: when calling a resource with a space, use a hyphen"),
"\n", styling.StyleItalic.Render("example: poke-cli ability strong-jaw"),
"\n", styling.StyleItalic.Render("example: poke-cli pokemon flutter-mane"),
+ "\n\n", fmt.Sprintf("%s %s", "↓ ctrl/cmd + click for docs/guides\n", styling.DocsLink),
)
fmt.Println(helpMessage)
}
diff --git a/cmd/ability/ability.go b/cmd/ability/ability.go
index 06c0c19..4a5cc30 100644
--- a/cmd/ability/ability.go
+++ b/cmd/ability/ability.go
@@ -88,21 +88,21 @@ func AbilityCommand() (string, error) {
capitalizedAbility := cases.Title(language.English).String(strings.ReplaceAll(abilityName, "-", " "))
output.WriteString(styling.StyleBold.Render(capitalizedAbility) + "\n")
- // API is missing some data for the short_effect for abilities from Generation 9.
- // If short_effect is empty, fallback to the move's flavor_text_entry.
- if englishShortEffect == "" {
- output.WriteString("Effect: " + englishFlavorEntry + "\n")
- } else {
- output.WriteString("Effect: " + englishShortEffect + "\n")
- }
-
- // Print the generation where the move was first introduced.
+ // Print the generation where the ability was first introduced.
generationParts := strings.Split(abilitiesStruct.Generation.Name, "-")
if len(generationParts) > 1 {
generationUpper := strings.ToUpper(generationParts[1])
- output.WriteString("Generation: " + generationUpper + "\n")
+ output.WriteString(fmt.Sprintf("%s First introduced in generation "+generationUpper+"\n", styling.ColoredBullet))
+ } else {
+ output.WriteString(fmt.Sprintf("%s Generation: Unknown\n", styling.ColoredBullet))
+ }
+
+ // API is missing some data for the short_effect for abilities from Generation 9.
+ // If short_effect is empty, fallback to the move's flavor_text_entry.
+ if englishShortEffect == "" {
+ output.WriteString(fmt.Sprintf("%s Effect: "+englishFlavorEntry, styling.ColoredBullet))
} else {
- output.WriteString("Generation: Unknown\n")
+ output.WriteString(fmt.Sprintf("%s Effect: "+englishShortEffect, styling.ColoredBullet))
}
if *pokemonFlag || *shortPokemonFlag {
diff --git a/demo.gif b/demo.gif
index 8fed910..adeeec4 100644
Binary files a/demo.gif and b/demo.gif differ
diff --git a/demo.tape b/demo.tape
index bcc6aba..a040354 100644
--- a/demo.tape
+++ b/demo.tape
@@ -63,7 +63,8 @@ Set Shell "bash"
Set FontSize 32
Set Width 2100
Set Height 1300
-Set TypingSpeed 85ms
+Set TypingSpeed 100ms
+Set Theme "tokyonight-storm"
Type "poke-cli pokemon charizard --abilities --stats --types"
diff --git a/docs/.dockerignore b/docs/.dockerignore
new file mode 100644
index 0000000..cbdbf54
--- /dev/null
+++ b/docs/.dockerignore
@@ -0,0 +1,3 @@
+# Environments
+.env
+.venv
\ No newline at end of file
diff --git a/docs/Dockerfile b/docs/Dockerfile
new file mode 100644
index 0000000..0dfc12d
--- /dev/null
+++ b/docs/Dockerfile
@@ -0,0 +1,23 @@
+# Dockerfile.prod
+FROM python:3.12-slim AS builder
+
+WORKDIR /build
+
+RUN pip install mkdocs mkdocs-material
+
+COPY mkdocs.yml /build/mkdocs.yml
+
+COPY docs/ /build/docs/
+
+RUN mkdocs build
+
+# --- Serve with lightweight HTTP server ---
+FROM python:3.12-slim
+
+WORKDIR /site
+
+COPY --from=builder /build/site /site
+
+EXPOSE 8080
+
+CMD ["python3", "-m", "http.server", "8080"]
\ No newline at end of file
diff --git a/docs/assets/DigitalGhostLogo-512.png b/docs/assets/DigitalGhostLogo-512.png
new file mode 100644
index 0000000..d984cc5
Binary files /dev/null and b/docs/assets/DigitalGhostLogo-512.png differ
diff --git a/docs/assets/ability.gif b/docs/assets/ability.gif
new file mode 100644
index 0000000..dd8d18f
Binary files /dev/null and b/docs/assets/ability.gif differ
diff --git a/docs/assets/move.gif b/docs/assets/move.gif
new file mode 100644
index 0000000..b8b53f4
Binary files /dev/null and b/docs/assets/move.gif differ
diff --git a/docs/assets/natures.gif b/docs/assets/natures.gif
new file mode 100644
index 0000000..c0f33b8
Binary files /dev/null and b/docs/assets/natures.gif differ
diff --git a/docs/assets/pokemon_abilities_moves.gif b/docs/assets/pokemon_abilities_moves.gif
new file mode 100644
index 0000000..8d51adf
Binary files /dev/null and b/docs/assets/pokemon_abilities_moves.gif differ
diff --git a/docs/assets/pokemon_image.gif b/docs/assets/pokemon_image.gif
new file mode 100644
index 0000000..1fc59a7
Binary files /dev/null and b/docs/assets/pokemon_image.gif differ
diff --git a/docs/assets/pokemon_stats_types.gif b/docs/assets/pokemon_stats_types.gif
new file mode 100644
index 0000000..68d9932
Binary files /dev/null and b/docs/assets/pokemon_stats_types.gif differ
diff --git a/docs/assets/search.gif b/docs/assets/search.gif
new file mode 100644
index 0000000..502cb20
Binary files /dev/null and b/docs/assets/search.gif differ
diff --git a/docs/assets/types.gif b/docs/assets/types.gif
new file mode 100644
index 0000000..1871281
Binary files /dev/null and b/docs/assets/types.gif differ
diff --git a/docs/commands.md b/docs/commands.md
new file mode 100644
index 0000000..04008cc
--- /dev/null
+++ b/docs/commands.md
@@ -0,0 +1,128 @@
+# Commands
+
+## main
+
+**Available Flags**
+
+* `--help | -h`
+* `--latest | -l`
+* `--version | -v`
+
+---
+
+## `ability`
+* Retrieve information about a specific ability, including its flavor text,
+the generation in which it first appeared, and a list of Pokémon that possess it.
+
+**Available Flags**
+
+* `--help | -h`
+* `--pokemon | -p`
+
+Example:
+```console
+$ poke-cli ability solar-power
+$ poke-cli ability solar-power --pokemon # list Pokémon that posses the ability
+```
+
+Output:
+
+
+
+---
+
+## `move`
+* Retrieve information about a specific move, including its type, power, PP, accuracy, category, etc.,
+and the move's effect.
+
+Example:
+```console
+$ poke-cli move dazzling-gleam
+```
+
+Output:
+
+
+
+---
+
+## `natures`
+* Retrieve a table of all natures and the stats they affect.
+
+Example:
+```console
+$ poke-cli natures
+```
+
+Output:
+
+
+
+---
+
+## `pokemon`
+* Retrieve information about a specific Pokémon such as available abilities, learnable moves, typing, and base stats. All data is based on generation 9.
+
+**Available Flags**
+
+* `--help | -h`
+* `--abilities | -a`
+* `--image=xx | -i=xx`
+* `--moves | -m`
+* `--stats | -s`
+* `--types | -t`
+
+Example:
+```console
+$ poke-cli pokemon rockruff --abilities --moves
+```
+
+Output:
+
+
+
+Example:
+```shell
+# choose between three sizes: 'sm', 'md', 'lg'
+$ poke-cli pokemon tyranitar --image=sm
+```
+
+Output:
+
+
+
+Example:
+```console
+$ poke-cli pokemon cacturne --stats --types
+```
+
+Output:
+
+
+
+---
+
+## `search`
+* Search for resources from different endpoints. Searchable endpoints include `ability`, `pokemon`, and `move`.
+
+Example:
+```console
+$ poke-cli search
+```
+
+Output:
+
+
+
+---
+
+## `types`
+* Retrieve details about a specific type and a damage relation table.
+
+Example:
+```console
+$ poke-cli types
+```
+Output:
+
+
\ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..4ac45b3
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,21 @@
+# Overview
+
+**Welcome!**
+
+This site is the central hub for detailed information on how to install, use, and learn about this project.
+
+The project originally began as a way to explore a new programming language to complement my existing skills in Python and SQL.
+I chose Go (Golang) and set out to build a CLI/TUI tool.
+
+Since then, the scope has expanded beyond a simple CLI/TUI. It now incorporates DevOps and Data Engineering practices,
+including CI/CD pipelines with GitHub Actions and data workflows using Airflow and AWS.
+
+## Demo
+Here is a quick demo of the CLI/TUI tool in action.
+
+
+## CI/CD Infrastructure
+*coming soon*
+
+## Data Infrastructure
+*coming soon*
\ No newline at end of file
diff --git a/flags/abilityflagset.go b/flags/abilityflagset.go
index 338ff1f..8f6fad0 100644
--- a/flags/abilityflagset.go
+++ b/flags/abilityflagset.go
@@ -33,7 +33,7 @@ func PokemonAbilitiesFlag(w io.Writer, endpoint string, abilityName string) erro
capitalizedEffect := cases.Title(language.English).String(strings.ReplaceAll(abilityName, "-", " "))
- if _, err := fmt.Fprintf(w, "\n%s\n\n", styling.StyleUnderline.Render("Pokemon with "+capitalizedEffect)); err != nil {
+ if _, err := fmt.Fprintf(w, "\n\n%s\n\n", styling.StyleUnderline.Render("Pokemon with "+capitalizedEffect)); err != nil {
return err
}
diff --git a/go.mod b/go.mod
index 1a6c1bd..18cf049 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@ require (
github.com/charmbracelet/bubbles v0.20.0
github.com/charmbracelet/bubbletea v1.2.4
github.com/charmbracelet/lipgloss v1.1.0
+ github.com/charmbracelet/x/exp/teatest v0.0.0-20250317102001-c803e5cafd0b
github.com/charmbracelet/x/term v0.2.1
github.com/disintegration/imaging v1.6.2
github.com/stretchr/testify v1.10.0
@@ -20,7 +21,6 @@ require (
github.com/charmbracelet/x/ansi v0.8.0 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/exp/golden v0.0.0-20241212170349-ad4b7ae0f25f // indirect
- github.com/charmbracelet/x/exp/teatest v0.0.0-20250317102001-c803e5cafd0b // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..a73ff08
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,49 @@
+site_name: poke-cli
+
+theme:
+ name: material
+ palette:
+ # Palette toggle for automatic mode
+ - media: "(prefers-color-scheme)"
+ toggle:
+ icon: material/brightness-auto
+ name: Switch to light mode
+
+ # Palette toggle for light mode
+ - media: "(prefers-color-scheme: light)"
+ scheme: default
+ toggle:
+ icon: material/brightness-7
+ name: Switch to dark mode
+
+ # Palette toggle for dark mode
+ - media: "(prefers-color-scheme: dark)"
+ scheme: slate
+ toggle:
+ icon: material/brightness-4
+ name: Switch to system preference
+ primary: red
+ features:
+ - navigation.footer
+ logo:
+ assets/DigitalGhostLogo-512.png
+
+repo_url: https://github.com/digitalghost-dev/poke-cli
+
+markdown_extensions:
+ - attr_list
+ - pymdownx.emoji:
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
+ - pymdownx.highlight:
+ anchor_linenums: true
+ line_spans: __span
+ pygments_lang_class: true
+ - pymdownx.inlinehilite
+ - pymdownx.snippets
+ - pymdownx.superfences
+
+extra:
+ social:
+ - icon: fontawesome/brands/docker
+ link: https://hub.docker.com/r/digitalghostdev/poke-cli
\ No newline at end of file
diff --git a/styling/styling.go b/styling/styling.go
index ee8b2d2..cdb1a68 100644
--- a/styling/styling.go
+++ b/styling/styling.go
@@ -17,6 +17,10 @@ var (
CheckboxStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FFCC00"))
KeyMenu = lipgloss.NewStyle().Foreground(lipgloss.Color("#777777"))
+ DocsLink = lipgloss.NewStyle().
+ Foreground(lipgloss.AdaptiveColor{Light: "#E1AD01", Dark: "#FFCC00"}).
+ Render("\x1b]8;;https://docs.poke-cli.com\x1b\\docs.poke-cli.com\x1b]8;;\x1b\\")
+
StyleBold = lipgloss.NewStyle().Bold(true)
StyleItalic = lipgloss.NewStyle().Italic(true)
StyleUnderline = lipgloss.NewStyle().Underline(true)
diff --git a/testdata/ability.golden b/testdata/ability.golden
index b5e0b5d..fcf850a 100644
--- a/testdata/ability.golden
+++ b/testdata/ability.golden
@@ -1,3 +1,3 @@
Clear Body
-Effect: Prevents stats from being lowered by other Pokémon.
-Generation: III
+• First introduced in generation III
+• Effect: Prevents stats from being lowered by other Pokémon.
\ No newline at end of file
diff --git a/testdata/ability_flag_pokemon.golden b/testdata/ability_flag_pokemon.golden
index 46e7bf8..c215a6d 100644
--- a/testdata/ability_flag_pokemon.golden
+++ b/testdata/ability_flag_pokemon.golden
@@ -1,6 +1,6 @@
Anger Point
-Effect: Raises Attack to the maximum of six stages upon receiving a critical hit.
-Generation: IV
+• First introduced in generation IV
+• Effect: Raises Attack to the maximum of six stages upon receiving a critical hit.
Pokemon with Anger Point
diff --git a/testdata/cli_help.golden b/testdata/cli_help.golden
index c116ad4..43bc33d 100644
--- a/testdata/cli_help.golden
+++ b/testdata/cli_help.golden
@@ -22,4 +22,7 @@
│ hint: when calling a resource with a space, use a hyphen │
│ example: poke-cli ability strong-jaw │
│ example: poke-cli pokemon flutter-mane │
+│ │
+│ ↓ ctrl/cmd + click for docs/guides │
+│ ]8;;https://docs.poke-cli.com\docs.poke-cli.com]8;;\ │
╰──────────────────────────────────────────────────────────╯