Skip to content

Commit 1192d4a

Browse files
Merge pull request #224 from digitalghost-dev/1.8.4
1.8.4
2 parents 975eb97 + a291efc commit 1192d4a

File tree

18 files changed

+491
-29
lines changed

18 files changed

+491
-29
lines changed

.github/workflows/ci.yml

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ on:
3131
- main
3232

3333
env:
34-
VERSION_NUMBER: 'v1.8.3'
34+
VERSION_NUMBER: 'v1.8.4'
3535
DOCKERHUB_REGISTRY_NAME: 'digitalghostdev/poke-cli'
3636
AWS_REGION: 'us-west-2'
3737

@@ -55,7 +55,7 @@ jobs:
5555
args: '-no-fail -fmt sarif -out results.sarif ./...'
5656

5757
- name: Upload SARIF Report
58-
uses: github/codeql-action/upload-sarif@v3
58+
uses: github/codeql-action/upload-sarif@v4
5959
with:
6060
sarif_file: results.sarif
6161

@@ -67,15 +67,19 @@ jobs:
6767
steps:
6868
- name: Checkout
6969
uses: actions/checkout@v6
70-
with:
71-
fetch-depth: 0
7270

73-
- name: Gitleaks
74-
uses: gitleaks/gitleaks-action@v2
75-
env:
76-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77-
GITLEAKS_CONFIG: ./gitleaks.toml
78-
GITLEAKS_VERSION: 8.29.0
71+
- name: Run Gitleaks
72+
run: |
73+
docker run --rm -v ${{ github.workspace }}:/path \
74+
ghcr.io/gitleaks/gitleaks:v8.29.0 \
75+
dir /path -c /path/gitleaks.toml --redact -v \
76+
--report-format sarif --report-path /path/gitleaks-results.sarif
77+
78+
- name: Upload SARIF Report
79+
if: always()
80+
uses: github/codeql-action/upload-sarif@v4
81+
with:
82+
sarif_file: gitleaks-results.sarif
7983

8084
build-linux-packages:
8185
runs-on: ubuntu-22.04
@@ -240,16 +244,39 @@ jobs:
240244
if [ "${{ needs.upload-deb-packages.result }}" != "success" ] || \
241245
[ "${{ needs.upload-rpm-packages.result }}" != "success" ] || \
242246
[ "${{ needs.upload-apk-packages.result }}" != "success" ]; then
243-
echo "⚠️ Some uploads failed! ⚠️"
247+
echo "⚠️ Some uploads failed"
244248
exit 1
245249
fi
246-
echo "✅ All packages uploaded successfully! ✅"
250+
echo "✅ All packages uploaded successfully"
247251
248-
build-docs-docker-image:
252+
validate-links:
249253
runs-on: ubuntu-22.04
250254
needs: [gitleaks]
251255
if: needs.gitleaks.result == 'success'
252256

257+
steps:
258+
- name: Checkout
259+
uses: actions/checkout@v6
260+
261+
- name: Check Links
262+
uses: lycheeverse/lychee-action@v2
263+
with:
264+
args: --verbose --config lychee.toml ./docs/**/*.md
265+
fail: false
266+
output: ./lychee-report.md
267+
268+
- name: Upload Report
269+
if: always()
270+
uses: actions/upload-artifact@v4
271+
with:
272+
name: lychee-report
273+
path: ./lychee-report.md
274+
275+
build-docs-docker-image:
276+
runs-on: ubuntu-22.04
277+
needs: [validate-links]
278+
if: needs.validate-links.result == 'success'
279+
253280
steps:
254281
- name: Checkout
255282
uses: actions/checkout@v6

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ poke-cli
1818

1919
# Output of the go coverage tool, specifically when used with LiteIDE
2020
*.out
21-
codecov*
2221

2322
# Dependency directories (remove the comment below to include it)
2423
# vendor/

.goreleaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ builds:
1414
- windows
1515
- darwin
1616
ldflags:
17-
- -s -w -X main.version=v1.8.3
17+
- -s -w -X main.version=v1.8.4
1818

1919
archives:
2020
- formats: [ 'zip' ]

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ RUN go mod download
88

99
COPY . .
1010

11-
RUN go build -ldflags "-X main.version=v1.8.3" -o poke-cli .
11+
RUN go build -ldflags "-X main.version=v1.8.4" -o poke-cli .
1212

1313
# build 2
1414
FROM --platform=$BUILDPLATFORM alpine:3.23

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<img width="425" src="poke-cli.png" alt="pokemon-logo"/>
33
<h4></h4>
44
<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">
5-
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v1.8.3?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
5+
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v1.8.4?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
66
<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">
77
</div>
88
<div align="center">
@@ -96,11 +96,11 @@ Cloudsmith is a fully cloud-based service that lets you easily create, store, an
9696
3. Choose how to interact with the container:
9797
* Run a single command and exit:
9898
```bash
99-
docker run --rm -it digitalghostdev/poke-cli:v1.8.3 <command> [subcommand] [flag]
99+
docker run --rm -it digitalghostdev/poke-cli:v1.8.4 <command> [subcommand] [flag]
100100
```
101101
* Enter the container and use its shell:
102102
```bash
103-
docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.8.3 -c "cd /app && exec sh"
103+
docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.8.4 -c "cd /app && exec sh"
104104
# placed into the /app directory, run the program with './poke-cli'
105105
# example: ./poke-cli ability swift-swim
106106
```

card_data/pipelines/poke_cli_dbt/dbt_project.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: 'poke_cli_dbt'
2-
version: '1.8.3'
2+
version: '1.8.4'
33

44
profile: 'poke_cli_dbt'
55

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import sys
2+
from pathlib import Path
3+
4+
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
5+
6+
import pytest
7+
import polars as pl
8+
import responses
9+
from pipelines.defs.extract.tcgdex.extract_sets import extract_sets_data
10+
11+
12+
@pytest.fixture
13+
def mock_api_response():
14+
"""Sample API responses matching tcgdex series format with sets"""
15+
return {
16+
"https://api.tcgdex.net/v2/en/series/me": {
17+
"id": "me",
18+
"name": "Mega Evolution",
19+
"sets": [
20+
{
21+
"id": "me01",
22+
"name": "Mega Evolution",
23+
"cardCount": {"official": 12, "total": 12},
24+
"logo": "https://example.com/me01.png",
25+
"symbol": "https://example.com/me01-symbol.png",
26+
},
27+
{
28+
"id": "me02",
29+
"name": "Phantasmal Flames",
30+
"cardCount": {"official": 25, "total": 25},
31+
"logo": "https://example.com/me02.png",
32+
"symbol": "https://example.com/me02-symbol.png",
33+
},
34+
],
35+
},
36+
"https://api.tcgdex.net/v2/en/series/sv": {
37+
"id": "sv",
38+
"name": "Scarlet & Violet",
39+
"sets": [
40+
{
41+
"id": "sv01",
42+
"name": "Scarlet & Violet",
43+
"cardCount": {"official": 198, "total": 258},
44+
"logo": "https://example.com/sv01.png",
45+
"symbol": "https://example.com/sv01-symbol.png",
46+
},
47+
{
48+
"id": "sv02",
49+
"name": "Paldea Evolved",
50+
"cardCount": {"official": 193, "total": 279},
51+
"logo": "https://example.com/sv02.png",
52+
"symbol": None,
53+
},
54+
],
55+
},
56+
"https://api.tcgdex.net/v2/en/series/swsh": {
57+
"id": "swsh",
58+
"name": "Sword & Shield",
59+
"sets": [
60+
{
61+
"id": "swsh1",
62+
"name": "Sword & Shield",
63+
"cardCount": {"official": 202, "total": 216},
64+
"logo": None,
65+
"symbol": "https://example.com/swsh1-symbol.png",
66+
},
67+
],
68+
},
69+
}
70+
71+
72+
@pytest.mark.benchmark
73+
@responses.activate
74+
def test_extract_sets_data_success(mock_api_response):
75+
"""Test successful extraction of sets from multiple series"""
76+
# Mock all API calls
77+
for url, response_data in mock_api_response.items():
78+
responses.add(
79+
responses.GET,
80+
url,
81+
json=response_data,
82+
status=200,
83+
)
84+
85+
result = extract_sets_data()
86+
87+
# Assertions
88+
assert isinstance(result, pl.DataFrame) # nosec
89+
assert len(result) == 5 # nosec (2 + 2 + 1 sets)
90+
assert set(result.columns) == { # nosec
91+
"series_id",
92+
"set_id",
93+
"set_name",
94+
"official_card_count",
95+
"total_card_count",
96+
"logo",
97+
"symbol",
98+
}
99+
assert set(result["series_id"].to_list()) == {"me", "sv", "swsh"} # nosec
100+
assert set(result["set_id"].to_list()) == {"me01", "me02", "sv01", "sv02", "swsh1"} # nosec
101+
102+
103+
@pytest.mark.benchmark
104+
@responses.activate
105+
def test_extract_sets_data_empty_sets(mock_api_response):
106+
"""Test extraction when a series has no sets"""
107+
# Modify one response to have empty sets
108+
mock_api_response["https://api.tcgdex.net/v2/en/series/me"]["sets"] = []
109+
110+
for url, response_data in mock_api_response.items():
111+
responses.add(
112+
responses.GET,
113+
url,
114+
json=response_data,
115+
status=200,
116+
)
117+
118+
result = extract_sets_data()
119+
120+
assert isinstance(result, pl.DataFrame) # nosec
121+
assert len(result) == 3 # nosec (0 + 2 + 1 sets)
122+
assert "me" not in result["series_id"].to_list() # nosec
123+
124+
125+
@pytest.mark.benchmark
126+
@responses.activate
127+
def test_extract_sets_data_null_card_counts():
128+
"""Test extraction with null card counts"""
129+
mock_responses = {
130+
"https://api.tcgdex.net/v2/en/series/me": {
131+
"id": "me",
132+
"name": "Mega Evolution",
133+
"sets": [],
134+
},
135+
"https://api.tcgdex.net/v2/en/series/sv": {
136+
"id": "sv",
137+
"name": "Scarlet & Violet",
138+
"sets": [
139+
{
140+
"id": "sv01",
141+
"name": "Scarlet & Violet",
142+
"cardCount": {},
143+
"logo": None,
144+
"symbol": None,
145+
},
146+
],
147+
},
148+
"https://api.tcgdex.net/v2/en/series/swsh": {
149+
"id": "swsh",
150+
"name": "Sword & Shield",
151+
"sets": [],
152+
},
153+
}
154+
155+
for url, response_data in mock_responses.items():
156+
responses.add(
157+
responses.GET,
158+
url,
159+
json=response_data,
160+
status=200,
161+
)
162+
163+
result = extract_sets_data()
164+
165+
assert isinstance(result, pl.DataFrame) # nosec
166+
assert len(result) == 1 # nosec
167+
assert result["official_card_count"].to_list()[0] is None # nosec
168+
assert result["total_card_count"].to_list()[0] is None # nosec

card_data/uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/card/cardinfo.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func resizeImage(img image.Image, width, height int) image.Image {
2222

2323
func CardImage(imageURL string) (string, error) {
2424
client := &http.Client{
25-
Timeout: time.Second * 15,
25+
Timeout: time.Second * 60,
2626
}
2727
parsedURL, err := url.Parse(imageURL)
2828
if err != nil || (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") {
@@ -38,8 +38,14 @@ func CardImage(imageURL string) (string, error) {
3838
return "", fmt.Errorf("non-200 response: %d", resp.StatusCode)
3939
}
4040

41+
// Read body into memory first to avoid timeout during decode
4142
limitedBody := io.LimitReader(resp.Body, 10*1024*1024)
42-
img, _, err := image.Decode(limitedBody)
43+
bodyBytes, err := io.ReadAll(limitedBody)
44+
if err != nil {
45+
return "", fmt.Errorf("failed to read image data: %w", err)
46+
}
47+
48+
img, _, err := image.Decode(bytes.NewReader(bodyBytes))
4349
if err != nil {
4450
return "", fmt.Errorf("failed to decode image: %w", err)
4551
}

cmd/card/cardlist.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ func CallCardData(url string) ([]byte, error) {
172172
req.Header.Add("Authorization", "Bearer sb_publishable_oondaaAIQC-wafhEiNgpSQ_reRiEp7j")
173173
req.Header.Add("Content-Type", "application/json")
174174

175-
client := &http.Client{Timeout: 15 * time.Second}
175+
client := &http.Client{Timeout: 60 * time.Second}
176176
resp, err := client.Do(req)
177177
if err != nil {
178178
return nil, fmt.Errorf("error making GET request: %w", err)

0 commit comments

Comments
 (0)