Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8a28c9c
Merge pull request #3815 from akshat-kumar-singhal/fix/flaky-cron-nil…
akshat-kumar-singhal Aug 13, 2026
bc271ff
chore(ci): pin ls-lint/action to node24 commit to clear Node 20 warni…
akshat-kumar-singhal Aug 13, 2026
aef1622
fix(grpc): guard the server handle so Run and Shutdown stop racing (#…
akshat-kumar-singhal Aug 15, 2026
9a9ea85
chore(ci): build the website workflows on Node 24 instead of EOL Node…
akshat-kumar-singhal Aug 15, 2026
7c0fad4
fix(examples): wait on a readiness signal instead of sleeping, and ma…
akshat-kumar-singhal Aug 17, 2026
f1e5c1a
feat(ai): add Embed capability to the LLM (#3757)
aryanmehrotra Aug 17, 2026
878b026
perf(http): opt-in O(1) trie router behind GOFR_ROUTER (#3759)
aryanmehrotra Aug 18, 2026
467b2ff
chore(deps): consolidate minor/patch dependency updates (2026-08-18) …
Umang01-hash Aug 18, 2026
24d51d6
fix(ci): wait for Example-Unit-Testing services to be ready, and pin …
akshat-kumar-singhal Aug 18, 2026
6ac1586
chore(ci): add concurrency groups and job timeouts, pin actions by SH…
akshat-kumar-singhal Aug 21, 2026
b15a97c
fix(ci): stop mutating go.mod mid-run; check submodule tidiness witho…
akshat-kumar-singhal Aug 21, 2026
b29f693
chore(deps): close the dependabot coverage gaps and retire EOL base i…
akshat-kumar-singhal Aug 21, 2026
1eea201
chore(deps): bump tj-actions/changed-files 47.0.0 -> 47.0.6 (#4049)
Umang01-hash Aug 24, 2026
a0dbf76
chore(deps): bump redis/go-redis/v9 9.21.0 -> 9.22.0 + regenerate moc…
Umang01-hash Aug 25, 2026
6cd9ac4
chore(deps): bump golang 1.26-alpine -> 1.27-alpine in examples/http-…
Umang01-hash Aug 27, 2026
7cbb41a
fix(http): characterize the request path and fix eleven defects it ex…
aryanmehrotra Aug 28, 2026
cf20ee0
perf(logging,http): skip request logs the level discards, and co-allo…
aryanmehrotra Aug 28, 2026
43cb128
update release version to v1.60.0
aryanmehrotra Aug 31, 2026
743fc4b
Merge remote-tracking branch 'origin/main' into release/v1.60.0
aryanmehrotra Aug 31, 2026
ec7793e
fix(ai): make Embed a method on ai.LLM instead of a type assertion (#…
aryanmehrotra Aug 31, 2026
5078adb
Merge remote-tracking branch 'origin/development' into release/v1.60.0
aryanmehrotra Aug 31, 2026
c817f71
fix(test): stop pinning the tracer scope name to a development build …
aryanmehrotra Aug 31, 2026
9f73308
Merge remote-tracking branch 'origin/development' into release/v1.60.0
aryanmehrotra Aug 31, 2026
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
24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@ version: 2
updates:
- package-ecosystem: "gomod"
open-pull-requests-limit: 10 # avoid spam, if no one reacts
# The tree has 32 go.mod directories. The globs below must cover all of
# them β€” `pkg/gofr/metrics/exporters/gcp` was matched by none of the
# original entries and so received no dependency updates at all, despite
# vendoring the GCP client libraries. When adding a module outside these
# paths, add its glob here too; nothing fails loudly when one is missed.
directories:
- "/"
- "/examples/*"
- "/pkg/gofr/datasource/*"
- "/pkg/gofr/datasource/file/*"
- "/pkg/gofr/datasource/kv-store/*"
- "/pkg/gofr/datasource/pubsub/*"
- "/pkg/gofr/metrics/exporters/*"
schedule:
interval: "weekly"

Expand All @@ -25,3 +31,21 @@ updates:
- "minor"
- "patch"

# Base images were previously unmanaged entirely, which is how
# examples/http-server sat on alpine:3.14 β€” end-of-support 2023-05-01, so no
# musl/busybox/OpenSSL patches for over three years. Grouped so a weekly
# patch bump across the 11 Dockerfiles arrives as one PR rather than 11.
- package-ecosystem: "docker"
open-pull-requests-limit: 10 # avoid spam, if no one reacts
directories:
- "/"
- "/docs"
- "/examples/*"
schedule:
interval: "weekly"
groups:
docker:
update-types:
- "minor"
- "patch"

138 changes: 124 additions & 14 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,29 @@ on:
- 'docs/**' # Ignore changes to docs folder
- '**/*.md'

# One in-flight run per ref. Pushing twice to a PR branch otherwise starts a
# second full 14-job matrix β€” including the Kafka/Redis/MySQL services and the
# Zipkin/MinIO containers β€” while the first is still running, and only the
# newer result is ever looked at.
#
# Cancellation is limited to pull_request on purpose. On `development` the runs
# are serialized merges rather than rapid re-pushes, so there is little to save,
# and `upload_coverage` publishes to qlty per push β€” cancelling that loses the
# coverage data point for a commit that will not be built again.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

# Define the jobs that this workflow will run
jobs:
# Job for testing the examples directory
Example-Unit-Testing:
name: Example Unit Testing (v${{ matrix.go-version }})πŸ› 
runs-on: ubuntu-latest
# Bounds a hung job at 30m instead of GitHub's 6h default. The retry action
# below caps the test step itself (5m x 2 attempts), but `Get dependencies`,
# the MinIO readiness poll and the s3 example test are otherwise unbounded.
timeout-minutes: 30
# Define a matrix strategy to test against multiple Go versions
strategy:
matrix:
Expand All @@ -38,6 +55,14 @@ jobs:
# Define service containers that tests depend on
services:
# Kafka service
#
# NOTE: the `bitnamilegacy` namespace is a frozen archive β€” Bitnami state
# it receives no further updates and "may be removed in the future". This
# image therefore still needs to move (to apache/kafka, or a mirror under
# gofr-dev), which is tracked separately in #3868: that migration rewrites
# the whole KAFKA_CFG_* block below, since those names are a Bitnami
# convention, and it cannot be validated without a live CI run. Kept here
# deliberately so this PR stays reviewable.
kafka:
image: bitnamilegacy/kafka:3.4.1
ports:
Expand All @@ -54,13 +79,30 @@ jobs:
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 1@127.0.0.1:9093
ALLOW_PLAINTEXT_LISTENER: yes
KAFKA_CFG_NODE_ID: 1
# kafka-topics.sh is on PATH in this image (/opt/bitnami/kafka/bin) and
# returns non-zero until the broker accepts connections. The 10s
# timeout is deliberate β€” the check starts a JVM, so the 5s used for
# redis/mysql would risk timing out on a broker that is actually fine.
options: >-
--health-cmd "kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --list"
--health-interval=10s
--health-timeout=10s
--health-retries=10

# Redis service
redis:
image: redis:7.0.5
ports:
- "2002:6379"
options: "--entrypoint redis-server"
# Without a health check the runner waits for the container to start,
# not for the service inside it to accept connections. The health
# options are appended to the existing --entrypoint override.
options: >-
--entrypoint redis-server
--health-cmd "redis-cli ping"
--health-interval=10s
--health-timeout=5s
--health-retries=5

# MySQL service
mysql:
Expand All @@ -70,6 +112,14 @@ jobs:
env:
MYSQL_ROOT_PASSWORD: "password"
MYSQL_DATABASE: "test"
# MySQL is the one that takes meaningfully long to accept connections
# after the container starts, so it is the one most likely to have been
# racing the tests.
options: >-
--health-cmd "mysqladmin ping -h 127.0.0.1 -ppassword"
--health-interval=10s
--health-timeout=5s
--health-retries=10

# Steps to execute for this job
steps:
Expand All @@ -95,8 +145,22 @@ jobs:
run: |
go mod download

# Same treatment as the MinIO step below: pin the image and wait for the
# service, not for `docker run -d` to return. `:latest` also meant the
# image could change under the repo without any commit.
- name: Start Zipkin
run: docker run -d -p 2005:9411 openzipkin/zipkin:latest
run: |
docker run -d --name zipkin -p 2005:9411 \
openzipkin/zipkin:3.6.1@sha256:d17e856dcbba7ffeefbbfc252f89ab78a4ab6faed47e646d46daad78f91b5ee2
for i in $(seq 1 30); do
if curl -fs http://localhost:2005/health >/dev/null; then
echo "Zipkin is ready"; exit 0
fi
echo "waiting for Zipkin... ($i)"; sleep 2
done
echo "::error::Zipkin failed to become ready after 60s"
docker logs zipkin || true
exit 1

# MinIO can't run as a GitHub Actions `services:` container because the
# stock image needs a `server /data` command, which services can't set.
Expand All @@ -122,13 +186,17 @@ jobs:
docker logs minio || true
exit 1

# Run tests with automatic retry on failures
- name: Test with Retry Logic
- name: Test
id: test
uses: nick-fields/retry@v4
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
with:
timeout_minutes: 5 # Maximum time for the tests to run
max_attempts: 2 # Retry up to 2 times if tests fail
# No retry. The example tests used to race their own server's boot β€” every one of them
# slept a fixed 100ms after `go main()` and hoped β€” and a retry turned that into a green
# tick. It equally hid a real regression that happened to pass on the second attempt.
# They now wait on a readiness signal (testutil.WaitFor*), so a failure here is a
# failure. The action is kept for its timeout_minutes.
max_attempts: 1
command: |
# The retry action runs this block with a plain shell (no errexit),
# unlike native `run:` steps that default to `bash -eo pipefail`.
Expand Down Expand Up @@ -170,6 +238,7 @@ jobs:
PKG-Unit-Testing:
name: PKG Unit Testing (v${{ matrix.go-version }})πŸ› 
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
go-version: ['1.26','1.25', '1.24']
Expand Down Expand Up @@ -200,7 +269,7 @@ jobs:
# Run pkg tests with automatic retry logic
- name: Test with Retry Logic
id: test
uses: nick-fields/retry@v4
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
with:
timeout_minutes: 5
max_attempts: 2
Expand Down Expand Up @@ -257,6 +326,7 @@ jobs:
parse_coverage:
name: Code Coverage
runs-on: ubuntu-latest
timeout-minutes: 10
# This job runs after both Example and PKG testing are complete
needs: [ Example-Unit-Testing,PKG-Unit-Testing ]
steps:
Expand Down Expand Up @@ -295,6 +365,7 @@ jobs:
Submodule-Unit-Testing:
name: Submodule Unit Testing (v${{ matrix.go-version }})πŸ› 
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
go-version: ['1.26','1.25', '1.24']
Expand Down Expand Up @@ -329,7 +400,7 @@ jobs:
# Test all submodules in parallel with retry logic
- name: Test Submodules with Retry and Parallelism
id: test_submodules
uses: nick-fields/retry@v4
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
with:
timeout_minutes: 5
max_attempts: 2
Expand Down Expand Up @@ -366,9 +437,15 @@ jobs:
# Extract module name (replace / with _)
module_name=$(echo "$module" | tr "/" "_")

# Download dependencies for the submodule
# Download dependencies for the submodule. Deliberately no
# `go mod tidy` here: tidy rewrites go.mod/go.sum in place, so the
# tests would run against whatever tidy resolved at that moment
# rather than against what the repo actually declares. A submodule
# with an incomplete committed go.mod would be silently repaired
# in the runner and pass, then fail for anyone who clones it β€”
# CI quietly fixing the exact defect it exists to report. Tidiness
# is checked without mutation in the code_quality job instead.
go mod download
go mod tidy

# Run tests with a focus on failed tests first
go test ./... -v -short -coverprofile="${module_name}.cov" -coverpkg=./...
Expand All @@ -391,6 +468,7 @@ jobs:
upload_coverage:
name: Upload CoverageπŸ“Š
runs-on: ubuntu-latest
timeout-minutes: 15
env:
QLTY_TOKEN: ${{ secrets.QLTY_TOKEN }}
QLTY_COVERAGE_TOKEN: ${{ secrets.QLTY_TOKEN }}
Expand Down Expand Up @@ -437,6 +515,9 @@ jobs:
code_quality:
name: Code QualityπŸŽ–οΈ
runs-on: ubuntu-latest
# golangci-lint gets --timeout=5m below; this bounds checkout, module
# download and the changed-files scan around it.
timeout-minutes: 20
outputs:
modules: ${{ steps.changed-submodules.outputs.modules }}
has_modules: ${{ steps.changed-submodules.outputs.has_modules }}
Expand All @@ -455,10 +536,33 @@ jobs:
- name: Get dependencies
run: go mod download

# Replaces the signal the `go mod tidy` in Submodule-Unit-Testing was
# accidentally providing. `-diff` (Go 1.23+) reports what tidy would
# change and exits non-zero, without writing anything β€” so an untidy
# go.mod is now reported instead of silently repaired mid-test-run.
#
# Scoped to the pkg/ modules, which are the ones that ship. All of them
# are tidy as of this change; the examples are excluded because
# examples/using-gcp-metrics is currently untidy and settling that is a
# dependency bump, not a CI fix.
- name: Check submodule go.mod tidiness
run: |
rc=0
while read -r mod; do
dir=$(dirname "$mod")
if ! out=$(cd "$dir" && go mod tidy -diff 2>&1); then
echo "::error file=$mod::$dir has an untidy go.mod/go.sum β€” run 'go mod tidy' there"
echo "$out"
rc=1
fi
done < <(find pkg -name go.mod)
if [ "$rc" -eq 0 ]; then echo "βœ… all pkg/ submodules are tidy"; fi
exit $rc

# Use the official golangci-lint action for the root module
# This action automatically detects changed files and only reports new issues
- name: Lint Root Module
uses: golangci/golangci-lint-action@v9
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
version: v2.12.2
only-new-issues: true
Expand All @@ -468,7 +572,7 @@ jobs:
# This implements a changed-files based approach as suggested by the maintainer
- name: Get Changed Files
id: changed-files
uses: tj-actions/changed-files@v47
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
with:
files: |
pkg/**/*.go
Expand Down Expand Up @@ -530,6 +634,9 @@ jobs:
lint_changed_submodules:
name: Lint SubmodulesπŸ”
runs-on: ubuntu-latest
# Must exceed the --timeout=9m passed to golangci-lint below, so a genuine
# lint timeout still reports as a lint failure rather than a killed job.
timeout-minutes: 20
needs: code_quality
if: needs.code_quality.outputs.has_modules == 'true'
strategy:
Expand All @@ -554,7 +661,7 @@ jobs:

# Use the official golangci-lint action for this submodule
- name: Lint ${{ matrix.module }}
uses: golangci/golangci-lint-action@v9
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
version: v2.12.2
working-directory: ${{ matrix.module }}
Expand All @@ -565,6 +672,7 @@ jobs:
linting_party:
name: Linting PartyπŸ₯³
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out code
uses: actions/checkout@v7
Expand All @@ -576,7 +684,9 @@ jobs:

# Check file naming conventions using ls-lint
- name: Check for file names errors
uses: ls-lint/action@v2.3.1
# Pinned to main: v2.3.1 still declares the deprecated node20 runtime.
# 0c7f19c ("chore: run on the node24 runtime") is not in a tagged release yet.
uses: ls-lint/action@0c7f19c04594e52a801dec991aae70a7ae5c6665 # main, node24 runtime
with:
config: .ls-lint.yml

Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/typos.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
name: Typos Check
# Mirrors go.yml's trigger block. The previous bare `push:`/`pull_request:` had
# no branch filter, so a PR raised from a branch in this repo ran the check
# twice β€” once for the push, once for the pull_request. Unlike go.yml there is
# no paths-ignore: prose is exactly what this check is for.
on:
push:
branches:
- main
- development
pull_request:
branches:
- main
- development

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
typos:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Checkout Code
uses: actions/checkout@v7
- name: typos-action
uses: crate-ci/typos@v1.48.0
uses: crate-ci/typos@8a48f81b6c64dcfea44b3633223084c4be58ac5f # v1.49.0
Loading
Loading