check / check (push) Canceled after 0s
Takes .golangci.yml, .dockerignore, .gitignore, .editorconfig, the workflow and REPO_POLICIES.md from sneak/prompts 0653579, with this repository's own entries after the shared content. Lint (golangci-lint v2.14.0) and test are Dockerfile phases that script/lint and script/test build alone with a new CACHEBUST value, keeping Go's and golangci-lint's caches; the image build depends on both. make fmt and make fmt-check also format the markdown with prettier, pinned in yarn.lock. The agent guidance moves to AGENTS.md. The Go code is fixed for what the new configuration finds, and the AS and prefix detail reads now return the rows' error after their loops. Model: opus-5-5
113 lines
2.3 KiB
Go
113 lines
2.3 KiB
Go
// Package main generates the embedded AS info data for the asinfo package
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/csv"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const asCsvURL = "https://github.com/ipverse/asn-info/raw/refs/heads/master/as.csv"
|
|
|
|
// ASInfo represents information about an Autonomous System
|
|
type ASInfo struct {
|
|
ASN int `json:"asn"`
|
|
Handle string `json:"handle"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
func main() {
|
|
// Configure logger to write to stderr
|
|
log.SetOutput(os.Stderr)
|
|
|
|
// Fetch the CSV data
|
|
log.Println("Fetching AS CSV data...")
|
|
|
|
req, err := http.NewRequestWithContext(
|
|
context.Background(), http.MethodGet, asCsvURL, nil)
|
|
if err != nil {
|
|
log.Fatalf("Failed to fetch CSV: %v", err)
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
log.Fatalf("Failed to fetch CSV: %v", err)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
log.Fatalf("Failed to fetch CSV: HTTP %d", resp.StatusCode)
|
|
}
|
|
|
|
// Parse CSV
|
|
reader := csv.NewReader(resp.Body)
|
|
|
|
// Read header
|
|
header, err := reader.Read()
|
|
if err != nil {
|
|
log.Fatalf("Failed to read CSV header: %v", err)
|
|
}
|
|
|
|
if len(header) != 3 || header[0] != "asn" || header[1] != "handle" ||
|
|
header[2] != "description" {
|
|
log.Fatalf("Unexpected CSV header: %v", header)
|
|
}
|
|
|
|
// Read all records
|
|
var asInfos []ASInfo
|
|
|
|
for {
|
|
record, err := reader.Read()
|
|
if errors.Is(err, io.EOF) {
|
|
break
|
|
}
|
|
|
|
if err != nil {
|
|
log.Printf("Error reading CSV record: %v", err)
|
|
|
|
continue
|
|
}
|
|
|
|
const expectedFields = 3
|
|
if len(record) != expectedFields {
|
|
log.Printf("Skipping invalid record: %v", record)
|
|
|
|
continue
|
|
}
|
|
|
|
asn, err := strconv.Atoi(record[0])
|
|
if err != nil {
|
|
log.Printf("Invalid ASN %q: %v", record[0], err)
|
|
|
|
continue
|
|
}
|
|
|
|
asInfos = append(asInfos, ASInfo{
|
|
ASN: asn,
|
|
Handle: strings.TrimSpace(record[1]),
|
|
Description: strings.TrimSpace(record[2]),
|
|
})
|
|
}
|
|
|
|
// Closed here rather than deferred: log.Fatalf exits without running
|
|
// deferred calls.
|
|
_ = resp.Body.Close()
|
|
|
|
log.Printf("Parsed %d AS records", len(asInfos))
|
|
|
|
// Convert to JSON and output to stdout
|
|
encoder := json.NewEncoder(os.Stdout)
|
|
encoder.SetIndent("", "\t")
|
|
|
|
err = encoder.Encode(asInfos)
|
|
if err != nil {
|
|
log.Fatalf("Failed to encode JSON: %v", err)
|
|
}
|
|
}
|