Skip to content
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
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ on:
- 'packaging/**'
- '.github/workflows/mcp-packaging.yml'
- '.github/workflows/mcp-registry-publish.yml'
- '.github/workflows/contributors.yml'
pull_request:
branches:
- main
Expand All @@ -49,6 +50,7 @@ on:
- 'packaging/**'
- '.github/workflows/mcp-packaging.yml'
- '.github/workflows/mcp-registry-publish.yml'
- '.github/workflows/contributors.yml'
env:
GOTESTCMD: "go test -timeout 1200s --tags \"sqlite_stackql\" -v ./..."
TESTSCRIPT: "test/deprecated/python/main.py"
Expand Down
80 changes: 80 additions & 0 deletions .github/workflows/contributors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: contributors

# Regenerates internal/stackql/contributors/contributors.csv, the leaderboard
# behind SHOW CONTRIBUTORS (issue #320), using stackql itself: human
# contributors who have starred the repo, contributions descending. Opens a
# PR so every change to the credit list is reviewed. PRs opened with the
# workflow token do not trigger CI; close and reopen the PR to run it.

on:
schedule:
- cron: '17 3 1 * *'
workflow_dispatch:

permissions:
contents: write
pull-requests: write

env:
CSV_PATH: internal/stackql/contributors/contributors.csv
# Machine accounts operating as regular user accounts (PAT-driven CI
# identities, AI coding agents with user accounts). GitHub Apps are
# excluded generically by the type and [bot] filters in the query.
DENYLIST: "'claude'"
# An API failure or truncated result must not replace a healthy list.
MIN_ROWS: 10

jobs:
contributors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: stackql/setup-stackql@v2.3.1

- name: Query contributors
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
stackql exec "REGISTRY PULL github;"
stackql exec \
--auth='{"github":{"type":"bearer","credentialsenvvar":"GITHUB_TOKEN"}}' \
--http.response.pageLimit=-1 --http.response.maxResults=100 \
--output csv \
"SELECT c.login AS contributor, c.contributions
FROM github.repos.contributors c
INNER JOIN github.activity.repo_stargazers s ON s.login = c.login
WHERE c.owner = 'stackql' AND c.repo = 'stackql'
AND s.owner = 'stackql' AND s.repo = 'stackql'
AND c.type = 'User'
AND c.login NOT LIKE '%[bot]'
AND c.login NOT IN (${DENYLIST})
ORDER BY c.contributions DESC, c.login ASC" > "${CSV_PATH}"

- name: Guard contributor count
run: |
count=$(tail -n +2 "${CSV_PATH}" | wc -l)
if [ "${count}" -le "${MIN_ROWS}" ]; then
echo "::error::contributor query returned ${count} rows (<= ${MIN_ROWS}), refusing to update ${CSV_PATH}"
exit 1
fi
echo "${count} contributors"

- name: Open PR on change
env:
GH_TOKEN: ${{ github.token }}
run: |
if git diff --quiet -- "${CSV_PATH}"; then
echo "leaderboard unchanged"
exit 0
fi
branch="contributors/$(date -u +%Y%m%d)"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -b "${branch}"
git add "${CSV_PATH}"
git commit -m "contributors: refresh leaderboard"
git push -u origin "${branch}"
gh pr create --base main --head "${branch}" \
--title "contributors: refresh leaderboard" \
--body "Regenerated by the contributors workflow. Human contributors who have starred the repo, contributions descending."
2 changes: 1 addition & 1 deletion cicd/version.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
MajorVersion=0
MinorVersion=10
MinorVersion=11
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/getkin/kin-openapi v0.88.0
github.com/google/go-jsonnet v0.17.0
github.com/google/uuid v1.6.0
github.com/jackc/pgtype v1.10.0
github.com/jackc/pgx/v5 v5.0.4
github.com/lib/pq v1.10.4
Expand Down Expand Up @@ -93,7 +94,6 @@ require (
github.com/google/flatbuffers v24.12.23+incompatible // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/jsonschema-go v0.4.3 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
Expand Down
2 changes: 1 addition & 1 deletion internal/stackql/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func init() {
rootCmd.PersistentFlags().BoolVarP(&runtimeCtx.VerboseFlag, dto.VerboseFlagKey, "v", false, "Verbose flag")
rootCmd.PersistentFlags().BoolVar(&runtimeCtx.DryRunFlag, dto.DryRunFlagKey, false, "dryrun flag; preprocessor only will run and output returned")
rootCmd.PersistentFlags().BoolVarP(&runtimeCtx.CSVHeadersDisable, dto.CSVHeadersDisableKey, "H", false, "Disable CSV headers flag")
rootCmd.PersistentFlags().StringVarP(&runtimeCtx.OutputFormat, dto.OutputFormatKey, "o", "table", "Output format, must be (json | jsonl | table | csv)")
rootCmd.PersistentFlags().StringVarP(&runtimeCtx.OutputFormat, dto.OutputFormatKey, "o", "table", "Output format, must be (json | jsonl | table | csv | text | otel)")
rootCmd.PersistentFlags().StringVarP(&runtimeCtx.OutfilePath, dto.OutfilePathKey, "f", "stdout", "Output file into which results are written")
rootCmd.PersistentFlags().StringVarP(&runtimeCtx.InfilePath, dto.InfilePathKey, "i", "stdin", "Input file from which queries are read")
rootCmd.PersistentFlags().StringVarP(&runtimeCtx.TemplateCtxFilePath, dto.TemplateCtxFilePathKey, "q", "", "Context file for templating")
Expand Down
18 changes: 18 additions & 0 deletions internal/stackql/contributors/contributors.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
contributor,contributions
general-kroll-4-life,627
jeffreyaven,50
Iqbalabdi,4
Sneha41sb,4
jthegedus,4
derek10cloud,3
nirmalpatel008,2
Racso-3141,1
adityagiri3600,1
datwiz,1
kieranrimmer,1
ryuichi-maeda,1
ryukinoz,1
sanketmp,1
soysaucewaso,1
tomekz,1
yunchengyang515,1
65 changes: 65 additions & 0 deletions internal/stackql/contributors/contributors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Package contributors credits the humans behind stackql: the vendored
// leaderboard behind SHOW CONTRIBUTORS (issue #320). contributors.csv is
// regenerated by the contributors workflow and compiled in, so the build
// stays hermetic and each release freezes its credits.
package contributors

import (
_ "embed"
"encoding/csv"
"strconv"
"strings"
"sync"
)

//go:embed contributors.csv
var contributorsCSV string //nolint:gochecknoglobals // embed target

// csvFields is the column count of contributors.csv: contributor,contributions.
const csvFields = 2

// Contributor is one leaderboard entry.
type Contributor interface {
GetLogin() string
GetContributions() int
}

type contributor struct {
login string
contributions int
}

func (c contributor) GetLogin() string { return c.login }
func (c contributor) GetContributions() int { return c.contributions }

//nolint:gochecknoglobals // parsed once
var (
parseOnce sync.Once
parsed []Contributor
)

// List returns the leaderboard in vendored order (contributions descending).
func List() []Contributor {
parseOnce.Do(func() { parsed = parse(contributorsCSV) })
return parsed
}

// parse skips the header and any malformed line.
func parse(raw string) []Contributor {
records, err := csv.NewReader(strings.NewReader(raw)).ReadAll()
if err != nil || len(records) == 0 {
return nil
}
rv := make([]Contributor, 0, len(records)-1)
for _, rec := range records[1:] {
if len(rec) != csvFields {
continue
}
n, convErr := strconv.Atoi(strings.TrimSpace(rec[1]))
if convErr != nil || strings.TrimSpace(rec[0]) == "" {
continue
}
rv = append(rv, contributor{login: strings.TrimSpace(rec[0]), contributions: n})
}
return rv
}
33 changes: 33 additions & 0 deletions internal/stackql/contributors/contributors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package contributors_test

import (
"testing"

"github.com/stackql/stackql/internal/stackql/contributors"
)

// The embedded leaderboard must be non-empty, ordered by contributions
// descending, and free of blank or automated logins.
func TestList_EmbeddedLeaderboard(t *testing.T) {
list := contributors.List()
if len(list) == 0 {
t.Fatal("embedded contributors.csv parsed to an empty leaderboard")
}
for i, c := range list {
if c.GetLogin() == "" || c.GetContributions() <= 0 {
t.Fatalf("entry %d is malformed: %q %d", i, c.GetLogin(), c.GetContributions())
}
if i > 0 && c.GetContributions() > list[i-1].GetContributions() {
t.Fatalf("entry %d (%s) breaks descending order", i, c.GetLogin())
}
}
if list[0].GetLogin() != "general-kroll-4-life" {
t.Fatalf("expected the project founder on top, got %q", list[0].GetLogin())
}
}

func TestList_IsStable(t *testing.T) {
if a, b := contributors.List(), contributors.List(); len(a) != len(b) || &a[0] != &b[0] {
t.Fatal("List() must parse once and return the same leaderboard")
}
}
2 changes: 2 additions & 0 deletions internal/stackql/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"time"

"github.com/stackql/any-sdk/pkg/logging"
"github.com/stackql/any-sdk/public/sqlengine"
Expand Down Expand Up @@ -124,6 +125,7 @@ func (dr *basicStackQLDriver) ProcessDryRun(query string) {
func (dr *basicStackQLDriver) ProcessQuery(query string) {
clonedCtx := dr.handlerCtx.Clone()
clonedCtx.SetRawQuery(query)
clonedCtx.SetQueryStartTime(time.Now())
responses, ok := dr.processQueryOrQueries(clonedCtx)
if ok {
for _, r := range responses {
Expand Down
10 changes: 10 additions & 0 deletions internal/stackql/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"path"
"strings"
"sync"
"time"

"github.com/stackql/any-sdk/pkg/constants"
"github.com/stackql/any-sdk/pkg/db/sqlcontrol"
Expand Down Expand Up @@ -57,6 +58,7 @@ type HandlerContext interface { //nolint:revive // don't mind stuttering this on
//
GetRawQuery() string
GetQuery() string
GetQueryStartTime() time.Time
GetRuntimeContext() dto.RuntimeCtx
GetProviders() map[string]provider.IProvider
GetControlAttributes() sqlcontrol.ControlAttributes
Expand All @@ -83,6 +85,7 @@ type HandlerContext interface { //nolint:revive // don't mind stuttering this on
SetCurrentProvider(string)
SetQuery(string)
SetRawQuery(string)
SetQueryStartTime(time.Time)
//
SetOutErrFile(io.Writer)
//
Expand Down Expand Up @@ -126,6 +129,7 @@ type standardHandlerContext struct {
providersMapMutex *sync.Mutex
rawQuery string
query string
queryStartTime time.Time
runtimeContext dto.RuntimeCtx
providers map[string]provider.IProvider
controlAttributes sqlcontrol.ControlAttributes
Expand Down Expand Up @@ -214,6 +218,10 @@ func (hc *standardHandlerContext) SetRawQuery(rq string) {
hc.rawQuery = rq
}

func (hc *standardHandlerContext) SetQueryStartTime(t time.Time) {
hc.queryStartTime = t
}

func (hc *standardHandlerContext) SetQuery(q string) {
hc.query = q
}
Expand All @@ -223,6 +231,7 @@ func (hc *standardHandlerContext) SetTxnCounterMgr(mgr txncounter.Manager) {
}

func (hc *standardHandlerContext) GetRawQuery() string { return hc.rawQuery }
func (hc *standardHandlerContext) GetQueryStartTime() time.Time { return hc.queryStartTime }
func (hc *standardHandlerContext) GetQuery() string { return hc.query }
func (hc *standardHandlerContext) GetRuntimeContext() dto.RuntimeCtx { return hc.runtimeContext }
func (hc *standardHandlerContext) GetProviders() map[string]provider.IProvider { return hc.providers }
Expand Down Expand Up @@ -568,6 +577,7 @@ func (hc *standardHandlerContext) Clone() HandlerContext {
providersMapMutex: hc.providersMapMutex,
drmConfig: hc.drmConfig,
rawQuery: hc.rawQuery,
queryStartTime: hc.queryStartTime,
runtimeContext: hc.runtimeContext,
currentProvider: hc.currentProvider,
providers: hc.providers,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package internaldto

import (
"time"

"github.com/stackql/any-sdk/pkg/dto"
"github.com/stackql/psql-wire/pkg/sqldata"
)

type OutputContext struct {
RuntimeContext dto.RuntimeCtx
Result sqldata.ISQLResultStream
// Query and StartTime describe the submitted statement; the otel writer
// stamps them on every record.
Query string
StartTime time.Time
}
Loading
Loading