Skip to content

Commit 5d532c9

Browse files
authored
Release 0.2.1: API version exposure + release automation (#139)
* Bump to 0.2.1, add API version constant, update User-Agent - Fix stale TypeScript VERSION (was still "0.2.0" in client.ts) - Add API_VERSION / apiVersion constant across all 5 SDKs, sourced from openapi.json info.version ("2026-01-26") - Include API version in User-Agent: basecamp-sdk-{lang}/{ver} (api:{apiVer}) - Clean up "Basecamp 3" branding → "Basecamp" in READMEs and comments - Update stale version references in kotlin/README.md, swift/README.md, and ruby/Gemfile.lock * Add make bump and make sync-api-version for release automation - scripts/bump-version.sh: updates all 8 SDK version locations + lockfile - scripts/sync-api-version.sh: reads openapi.json info.version, updates API_VERSION constants in all 5 SDKs - Both scripts use portable sed (temp file, no -i flag) for Linux compat - make sync-api-version hooked into smithy-build for automatic sync - make sync-api-version-check wired into make check to catch drift - make bump VERSION=x.y.z validates strict semver format * Fix User-Agent doc comments to reflect new format * Address PR review: fix check recipe, jq guard, README, stderr redirect - Fix &&/|| operator precedence in sync-api-version-check by using ; separators so each grep runs independently - Add jq availability guard to sync-api-version-check - Use BasecampConfig.DEFAULT_USER_AGENT in Kotlin README instead of literal Kotlin string-template syntax that renders wrong in Markdown - Stop suppressing npm stderr in bump-version.sh * Preserve file permissions in sedi helper Use cat+rm instead of mv so the original file's inode and permissions are retained. mktemp creates files with mode 600, and mv would replace the target with those restrictive permissions.
1 parent 38c0cbe commit 5d532c9

File tree

19 files changed

+183
-29
lines changed

19 files changed

+183
-29
lines changed

Makefile

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Orchestrates both Smithy spec and Go SDK
44

5-
.PHONY: all check clean help provenance-sync provenance-check sync-status
5+
.PHONY: all check clean help provenance-sync provenance-check sync-status bump sync-api-version sync-api-version-check
66

77
# Default: run all checks
88
all: check
@@ -23,14 +23,15 @@ smithy-mapper:
2323
@echo "==> Building Smithy OpenAPI mapper..."
2424
cd spec/smithy-bare-arrays && ./gradlew publishToMavenLocal --quiet
2525

26-
# Build OpenAPI from Smithy (also regenerates behavior model)
26+
# Build OpenAPI from Smithy (also regenerates behavior model + syncs API version)
2727
smithy-build: behavior-model smithy-mapper
2828
@echo "==> Building OpenAPI from Smithy..."
2929
cd spec && smithy build
3030
cp spec/build/smithy/openapi/openapi/Basecamp.openapi.json openapi.json
3131
@echo "==> Post-processing OpenAPI for Go types..."
3232
./scripts/enhance-openapi-go-types.sh
3333
@echo "Updated openapi.json"
34+
@$(MAKE) sync-api-version
3435

3536
# Check that openapi.json is up to date
3637
smithy-check: smithy-validate smithy-mapper
@@ -120,6 +121,35 @@ sync-status:
120121
--jq '[.files[] | select(.filename | startswith("app/controllers/"))] | if length == 0 then " (no changes in app/controllers/)" else .[] | " " + .status[:1] + " " + .filename end'; \
121122
fi
122123

124+
#------------------------------------------------------------------------------
125+
# Version management
126+
#------------------------------------------------------------------------------
127+
128+
# Bump SDK version across all languages: make bump VERSION=x.y.z
129+
bump:
130+
ifndef VERSION
131+
$(error VERSION is required. Usage: make bump VERSION=x.y.z)
132+
endif
133+
@./scripts/bump-version.sh $(VERSION)
134+
135+
# Sync API_VERSION constants from openapi.json info.version
136+
sync-api-version:
137+
@./scripts/sync-api-version.sh
138+
139+
# Check that API_VERSION constants match openapi.json info.version
140+
sync-api-version-check:
141+
@echo "==> Checking API version freshness..."
142+
@command -v jq > /dev/null 2>&1 || { echo "ERROR: jq not found. Install jq to run sync-api-version-check (used by 'make check')."; exit 1; }
143+
@API_VER=$$(jq -r '.info.version' openapi.json); \
144+
ok=true; \
145+
grep -q "const APIVersion = \"$$API_VER\"" go/pkg/basecamp/version.go || ok=false; \
146+
grep -q "export const API_VERSION = \"$$API_VER\"" typescript/src/client.ts || ok=false; \
147+
grep -q "API_VERSION = \"$$API_VER\"" ruby/lib/basecamp/version.rb || ok=false; \
148+
grep -q "const val API_VERSION = \"$$API_VER\"" kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/BasecampConfig.kt || ok=false; \
149+
grep -q "public static let apiVersion = \"$$API_VER\"" swift/Sources/Basecamp/BasecampConfig.swift || ok=false; \
150+
if [ "$$ok" = false ]; then echo "ERROR: API_VERSION constants are out of date. Run 'make sync-api-version'"; exit 1; fi
151+
@echo "API version constants are up to date"
152+
123153
#------------------------------------------------------------------------------
124154
# Go SDK targets (delegates to go/Makefile)
125155
#------------------------------------------------------------------------------
@@ -344,7 +374,7 @@ swift-clean:
344374
#------------------------------------------------------------------------------
345375

346376
# Run all checks (Smithy + Go + TypeScript + Ruby + Kotlin + Swift + Behavior Model + Conformance + Provenance)
347-
check: smithy-check behavior-model-check provenance-check go-check-drift kt-check-drift go-check ts-check rb-check kt-check swift-check conformance
377+
check: smithy-check behavior-model-check provenance-check sync-api-version-check go-check-drift kt-check-drift go-check ts-check rb-check kt-check swift-check conformance
348378
@echo "==> All checks passed"
349379

350380
# Clean all build artifacts
@@ -422,6 +452,11 @@ help:
422452
@echo " provenance-check Verify Go embedded provenance is up to date"
423453
@echo " sync-status Show upstream changes since last spec sync"
424454
@echo ""
455+
@echo "Version:"
456+
@echo " bump VERSION=x.y.z Bump SDK version across all languages"
457+
@echo " sync-api-version Sync API_VERSION from openapi.json"
458+
@echo " sync-api-version-check Verify API_VERSION constants are up to date"
459+
@echo ""
425460
@echo "Combined:"
426461
@echo " check Run all checks (Smithy + Go + TypeScript + Ruby + Swift + Conformance + Provenance)"
427462
@echo " clean Remove all build artifacts"

go/pkg/basecamp/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
// Note: Default retry/backoff values are now in http.go as exported constants.
2121

2222
// DefaultUserAgent is the default User-Agent header value.
23-
const DefaultUserAgent = "basecamp-sdk-go/" + Version
23+
const DefaultUserAgent = "basecamp-sdk-go/" + Version + " (api:" + APIVersion + ")"
2424

2525
// Client is an HTTP client for the Basecamp API.
2626
// Client holds shared resources and is used to create AccountClient instances

go/pkg/basecamp/version.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
package basecamp
22

33
// Version is the current version of the Basecamp Go SDK.
4-
const Version = "0.2.0"
4+
const Version = "0.2.1"
5+
6+
// APIVersion is the Basecamp API version this SDK targets.
7+
const APIVersion = "2026-01-26"

kotlin/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![GitHub Packages](https://img.shields.io/badge/GitHub%20Packages-com.basecamp%3Abasecamp--sdk-blue)](https://github.com/basecamp/basecamp-sdk/packages)
55
[![Test](https://github.com/basecamp/basecamp-sdk/actions/workflows/test.yml/badge.svg)](https://github.com/basecamp/basecamp-sdk/actions/workflows/test.yml)
66

7-
Official Kotlin SDK for the [Basecamp 3 API](https://github.com/basecamp/bc3-api).
7+
Official Kotlin SDK for the [Basecamp API](https://github.com/basecamp/bc3-api).
88

99
## Features
1010

@@ -41,7 +41,7 @@ repositories {
4141
}
4242

4343
dependencies {
44-
implementation("com.basecamp:basecamp-sdk:0.1.1")
44+
implementation("com.basecamp:basecamp-sdk:0.2.1")
4545
}
4646
```
4747

@@ -95,7 +95,7 @@ val client = BasecampClient {
9595
| Option | Default | Description |
9696
|--------|---------|-------------|
9797
| `baseUrl` | `https://3.basecampapi.com` | Basecamp API base URL |
98-
| `userAgent` | `basecamp-sdk-kotlin/0.1.1` | User-Agent header |
98+
| `userAgent` | `BasecampConfig.DEFAULT_USER_AGENT` | User-Agent header |
9999
| `enableRetry` | `true` | Automatic retry on 429/503 |
100100
| `enableCache` | `false` | ETag-based HTTP caching |
101101
| `timeout` | `30s` | Request timeout |

kotlin/sdk/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
group = "com.basecamp"
8-
version = "0.2.0"
8+
version = "0.2.1"
99

1010
kotlin {
1111
jvm()

kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/BasecampConfig.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ data class BasecampConfig(
2828
val baseRetryDelay: Duration = 1.seconds,
2929
) {
3030
companion object {
31-
const val VERSION = "0.1.1"
31+
const val VERSION = "0.2.1"
32+
const val API_VERSION = "2026-01-26"
3233
const val DEFAULT_BASE_URL = "https://3.basecampapi.com"
33-
const val DEFAULT_USER_AGENT = "basecamp-sdk-kotlin/$VERSION"
34+
const val DEFAULT_USER_AGENT = "basecamp-sdk-kotlin/$VERSION (api:$API_VERSION)"
3435
const val DEFAULT_MAX_RETRIES = 3
3536
const val DEFAULT_MAX_PAGES = 10_000
3637
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@37signals/basecamp",
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"private": true,
55
"description": "TypeScript SDK for the Basecamp API",
66
"engines": {

ruby/Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
basecamp-sdk (0.2.0)
4+
basecamp-sdk (0.2.1)
55
faraday (~> 2.0)
66
zeitwerk (~> 2.6)
77

@@ -161,7 +161,7 @@ CHECKSUMS
161161
addressable (2.8.8) sha256=7c13b8f9536cf6364c03b9d417c19986019e28f7c00ac8132da4eb0fe393b057
162162
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
163163
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
164-
basecamp-sdk (0.2.0)
164+
basecamp-sdk (0.2.1)
165165
bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
166166
concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
167167
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a

ruby/lib/basecamp/http.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module Basecamp
1010
# This is an internal class used by Client; you typically don't use it directly.
1111
class Http
1212
# Default User-Agent header
13-
USER_AGENT = "basecamp-sdk-ruby/#{VERSION}".freeze
13+
USER_AGENT = "basecamp-sdk-ruby/#{VERSION} (api:#{API_VERSION})".freeze
1414

1515
# @param config [Config] configuration settings
1616
# @param token_provider [TokenProvider, nil] OAuth token provider (deprecated, use auth_strategy)

ruby/lib/basecamp/version.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# frozen_string_literal: true
22

33
module Basecamp
4-
VERSION = "0.2.0"
4+
VERSION = "0.2.1"
5+
API_VERSION = "2026-01-26"
56
end

0 commit comments

Comments
 (0)