Skip to content

chore(deps): bump base64 from 0.22.1 to 0.23.1 #66

chore(deps): bump base64 from 0.22.1 to 0.23.1

chore(deps): bump base64 from 0.22.1 to 0.23.1 #66

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
# Default types miss title-only edits. Label changes must also re-run the
# version suggestion because the prerelease channel comes from a label.
types: [opened, edited, reopened, synchronize, labeled, unlabeled]
schedule:
# Weekly cargo-audit sweep for advisories disclosed after dependencies land.
# Use an off-peak minute rather than :00 or :30.
- cron: "23 5 * * 2"
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build
run: cargo build
- name: Run tests
# This crate has no library target, so --lib would fail. Select the
# fixture-only conformance target while keeping live_db in its
# dedicated SQL Server job below.
run: cargo test --bins --test conformance
- name: Clippy
run: cargo clippy --all-targets -- -D warnings
- name: Check formatting
run: cargo fmt --all -- --check
explain-package:
name: EXPLAIN parser package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
# Installs the pnpm version pinned by "packageManager" in
# explain/package.json. Corepack is not used because the copy bundled
# with Node 22.13 carries stale npm registry signing keys and fails
# with "Cannot find matching keyid" when it resolves pnpm.
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
package_json_file: explain/package.json
- name: Setup Node
uses: actions/setup-node@v5
with:
# pnpm 11.23 requires Node 22.13 or newer.
node-version: "22.13"
- name: Install dependencies
working-directory: explain
run: pnpm install --frozen-lockfile
- name: Typecheck
working-directory: explain
run: pnpm typecheck
- name: Test
working-directory: explain
run: pnpm test
- name: Build
working-directory: explain
run: pnpm build
validate-manifest:
name: Validate .tabularium manifest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
# registry.tabularis.dev serves the driver-kind schema including the
# additive explain_parsers field from core PR #688, so the whole
# manifest is validated against the live validator.
- name: Validate manifest against the live registry schema
run: |
npx --yes @tabularium/cli validate .tabularium \
--registry https://registry.tabularis.dev --kind driver
live-db-integration:
name: Live SQL Server integration
runs-on: ubuntu-latest
# SQL Server needs more startup time and memory than PostgreSQL. GitHub's
# hosted runner has sufficient memory; generous health retries wait for
# readiness without a fixed sleep.
services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
ports:
- 1433:1433
env:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: "Str0ng!Passw0rd"
options: >-
--health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'Str0ng!Passw0rd' -C -Q 'SELECT 1' -b"
--health-interval 10s
--health-timeout 5s
--health-start-period 20s
--health-retries 30
steps:
- uses: actions/checkout@v7
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build
run: cargo build
- name: Run live-database integration test
env:
SQLSERVER_PLUGIN_BIN: ${{ github.workspace }}/target/debug/sqlserver-plugin
SQLSERVER_TEST_HOST: 127.0.0.1
SQLSERVER_TEST_PORT: 1433
SQLSERVER_TEST_USER: sa
SQLSERVER_TEST_PASSWORD: "Str0ng!Passw0rd"
SQLSERVER_TEST_DATABASE: tabularis_test
run: cargo test --test live_db -- --test-threads=1
pr-title:
name: PR title (Conventional Commits)
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
pull-requests: read
steps:
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
version-suggestion:
name: Version suggestion
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
# Classify the PR title's Conventional Commits type + breaking-change
# flag into a version-bump class. Requires the prerelease:* label to
# know which channel (alpha/beta/rc/stable) to suggest — see README's
# "Contributing: PR Titles & Versioning" for the full convention.
- name: Classify PR title and resolve prerelease channel
id: classify
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
PR_LABELS: ${{ toJson(github.event.pull_request.labels) }}
run: |
PATTERN='^([a-zA-Z]+)(\(([^)]+)\))?(!)?: (.+)$'
if [[ "$PR_TITLE" =~ $PATTERN ]]; then
TYPE="${BASH_REMATCH[1]}"
BANG="${BASH_REMATCH[4]}"
else
echo "::error::PR title does not match Conventional Commits format (type: subject) — cannot classify."
exit 1
fi
BREAKING=false
[ -n "$BANG" ] && BREAKING=true
if echo "$PR_BODY" | grep -qiE "^BREAKING[ -]CHANGE:"; then
BREAKING=true
fi
case "$TYPE" in
feat) CLASS="minor" ;;
fix|refactor|perf) CLASS="patch" ;;
docs|style|chore|test|ci|build) CLASS="none" ;;
*) CLASS="none" ;;
esac
[ "$BREAKING" = true ] && CLASS="major"
CHANNEL=$(echo "$PR_LABELS" | jq -r '[.[] | select(.name | startswith("prerelease:")) | .name][0] // ""' | sed 's/^prerelease://')
if [ -z "$CHANNEL" ]; then
echo "::error::No prerelease:alpha|beta|rc|stable label found on this PR. Add one so the version suggestion knows which channel to target — see README's 'Contributing: PR Titles & Versioning'."
exit 1
fi
case "$CHANNEL" in
alpha|beta|rc|stable) ;;
*) echo "::error::Unrecognized prerelease label value '$CHANNEL' — expected alpha, beta, rc, or stable."; exit 1 ;;
esac
{
echo "type=$TYPE"
echo "breaking=$BREAKING"
echo "class=$CLASS"
echo "channel=$CHANNEL"
} >> "$GITHUB_OUTPUT"
- name: Resolve baseline version
id: baseline
run: |
git fetch origin main --tags --quiet
TAG=$(git -C . describe --tags --abbrev=0 origin/main 2>/dev/null || true)
if [ -n "$TAG" ]; then
BASELINE="${TAG#v}"
else
BASELINE=$(git show origin/main:.tabularium | jq -r .version)
fi
echo "version=$BASELINE" >> "$GITHUB_OUTPUT"
- name: Compute suggestion, manage comment
uses: actions/github-script@v9
with:
script: |
const classification = "${{ steps.classify.outputs.class }}";
const channel = "${{ steps.classify.outputs.channel }}";
const type = "${{ steps.classify.outputs.type }}";
const breaking = "${{ steps.classify.outputs.breaking }}" === "true";
const baselineStr = "${{ steps.baseline.outputs.version }}";
const marker = "<!-- version-suggestion-bot";
function parseVersion(v) {
const m = v.match(/^(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z]+)\.(\d+))?$/);
if (!m) throw new Error(`Cannot parse version: ${v}`);
return {
major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]),
stage: m[4] || null, stageNum: m[5] ? Number(m[5]) : null,
};
}
function formatVersion(v) {
const base = `${v.major}.${v.minor}.${v.patch}`;
return v.stage ? `${base}-${v.stage}.${v.stageNum}` : base;
}
function bumpStable(v, cls) {
const out = { major: v.major, minor: v.minor, patch: v.patch, stage: null, stageNum: null };
if (cls === "major") { out.major += 1; out.minor = 0; out.patch = 0; }
else if (cls === "minor") { out.minor += 1; out.patch = 0; }
else if (cls === "patch") { out.patch += 1; }
return out;
}
function computeNextVersion(baselineStr, classification, channelLabel) {
const baseline = parseVersion(baselineStr);
if (channelLabel === "stable") {
if (baseline.stage) {
return formatVersion({ major: baseline.major, minor: baseline.minor, patch: baseline.patch, stage: null, stageNum: null });
}
return formatVersion(bumpStable(baseline, classification));
}
if (baseline.stage === channelLabel) {
return formatVersion({ ...baseline, stageNum: baseline.stageNum + 1 });
}
let base = { major: baseline.major, minor: baseline.minor, patch: baseline.patch };
if (!baseline.stage) {
const bumped = bumpStable(baseline, classification);
base = { major: bumped.major, minor: bumped.minor, patch: bumped.patch };
}
return formatVersion({ ...base, stage: channelLabel, stageNum: 1 });
}
const prNumber = context.payload.pull_request.number;
// Find our most recent, not-yet-minimized comment on this PR.
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
per_page: 100,
});
const ours = comments.filter(c => c.body.includes(marker));
const previous = ours.length ? ours[ours.length - 1] : null;
let previousClassification = null;
if (previous) {
const m = previous.body.match(/classification=([\w-]+:[\w-]+:[\w-]+)/);
previousClassification = m ? m[1] : null;
}
const currentClassification = `${type}:${classification}:${channel}`;
if (classification === "none") {
if (previous && previousClassification !== currentClassification) {
// Was suggesting something (or saying "none" for a different
// reason/channel), now saying "none" for this reason — say so
// once, then stop.
await minimizePrevious();
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `No release needed for this PR (\`${type}\`).\n\n${marker} classification=${currentClassification} -->`,
});
}
// Otherwise: never suggested anything, or already said "none" — stay silent.
return;
}
if (previous && previousClassification === currentClassification) {
// Meaningful classification hasn't changed since the last comment.
return;
}
async function minimizePrevious() {
if (!previous) return;
// REST comment objects expose node_id directly — no separate
// lookup needed to get the GraphQL node id.
await github.graphql(
`mutation($id: ID!) { minimizeComment(input: { subjectId: $id, classifier: OUTDATED }) { clientMutationId } }`,
{ id: previous.node_id }
);
}
const suggested = computeNextVersion(baselineStr, classification, channel);
const tag = `v${suggested}`;
await minimizePrevious();
const breakingNote = breaking ? " (breaking change)" : "";
const body = [
`### Version suggestion`,
``,
`Based on this PR's title (\`${type}\`${breakingNote}) and the \`prerelease:${channel}\` label:`,
``,
`| | |`,
`|---|---|`,
`| Current | \`${baselineStr}\` |`,
`| Suggested next tag | \`${tag}\` |`,
``,
`This is informational only — no tag or release is created automatically yet.`,
``,
`${marker} classification=${currentClassification} -->`,
].join("\n");
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
markdownlint:
name: Markdown lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Run markdownlint
run: npx --yes markdownlint-cli "**/*.md"
audit:
name: Security audit
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
# Scheduled audit-check runs can file or update tracking issues.
issues: write
steps:
- uses: actions/checkout@v7
- uses: rustsec/audit-check@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
# RUSTSEC-2026-0235 affects rkyv 0.7.46, present only because
# rust_decimal declares an optional rkyv feature. This plugin does
# not enable it (`cargo tree -i rkyv` has no path), so no rkyv code
# is compiled into the shipped binary. Re-check whenever
# rust_decimal is upgraded or its enabled features change.
ignore: RUSTSEC-2026-0235