diff --git a/.github/actions/install-tiledb/action.yml b/.github/actions/install-tiledb/action.yml index 74626ff8..431d0584 100644 --- a/.github/actions/install-tiledb/action.yml +++ b/.github/actions/install-tiledb/action.yml @@ -4,12 +4,13 @@ description: Install TileDB inputs: version: description: "The version of TileDB to install" - required: true + required: false linkage: description: "Whether to dynamically or statically link TileDB" - required: true + required: false + default: dynamic platform: - description: "Override automatica platform detection." + description: "Override automatic platform detection." required: false runs: @@ -22,6 +23,24 @@ runs: - name: Install Requests run: pip install requests shell: bash + - name: Detect Version + id: version + env: + TDB_VERSION: ${{ inputs.version }} + shell: python + run: | + import json + import os + import subprocess as sp + + version = os.environ["TDB_VERSION"] + if not version.strip(): + data = sp.check_output("cargo metadata --format-version 1", shell=True) + data = json.loads(data) + version = data["metadata"]["libtiledb"]["version"] + + with open(os.environ["GITHUB_OUTPUT"], 'w') as handle: + handle.write("version={}\n".format(version)) - name: Detect Platform id: platform env: @@ -47,9 +66,9 @@ runs: handle.write("platform={}\n".format(platform)) - name: Locate Upstream TileDB Tarball id: upstream-tarball - if: ${{ inputs.version != 'main' && inputs.linkage != 'static' }} + if: ${{ steps.version.outputs.version != 'main' && inputs.linkage != 'static' }} env: - TDB_VERSION: ${{ inputs.version }} + TDB_VERSION: ${{ steps.version.outputs.version }} TDB_LINKAGE: ${{ inputs.linkage }} TDB_PLATFORM: ${{ steps.platform.outputs.platform }} shell: python @@ -83,9 +102,9 @@ runs: handle.write("sha256={}\n".format(candidates[0][1])) - name: Locate Custom TileDB Tarball id: custom-tarball - if: ${{ inputs.version == 'main' || inputs.linkage == 'static' }} + if: ${{ steps.version.outputs.version == 'main' || inputs.linkage == 'static' }} env: - TDB_VERSION: ${{ inputs.version }} + TDB_VERSION: ${{ steps.version.outputs.version }} TDB_LINKAGE: ${{ inputs.linkage }} TDB_PLATFORM: ${{ steps.platform.outputs.platform }} shell: python diff --git a/.github/workflows/nightly-ci.yml b/.github/workflows/nightly-ci.yml index 34bb6893..e0b75103 100644 --- a/.github/workflows/nightly-ci.yml +++ b/.github/workflows/nightly-ci.yml @@ -33,7 +33,6 @@ jobs: - name: Install TileDB uses: ./.github/actions/install-tiledb with: - version: "main" linkage: ${{ matrix.linkage }} - name: Install Rust ${{ matrix.rust }} uses: dtolnay/rust-toolchain@master diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml index c59955f8..a2aa2a1b 100644 --- a/.github/workflows/pr-ci.yml +++ b/.github/workflows/pr-ci.yml @@ -27,9 +27,6 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Install TileDB uses: ./.github/actions/install-tiledb - with: - version: "main" - linkage: "dynamic" - name: Build run: cargo build --all-targets --all-features - name: Test @@ -52,9 +49,6 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Install TileDB uses: ./.github/actions/install-tiledb - with: - version: "main" - linkage: "dynamic" - name: Check Formatting run: cargo fmt --quiet --check - name: Lint @@ -75,15 +69,31 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Install TileDB uses: ./.github/actions/install-tiledb - with: - version: "main" - linkage: "dynamic" - name: Check Formatting run: cargo fmt --quiet --check - name: Lint run: cargo clippy --no-deps --all-targets --all-features -- -Dwarnings + check-pr-title: + name: "Check Title Format" + runs-on: ubuntu-latest + steps: + - name: "Check Title Format" + shell: python + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + import os + import re + + PAT = re.compile(r"^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*)") + if not PAT.match(os.environ["PR_TITLE"]): + print("The pull request title does not match Conventional Commits syntax") + print("See: https://www.conventionalcommits.org/en/v1.0.0/") + exit(1) + check-api-coverage: + name: "Check API Coverage" runs-on: ubuntu-latest steps: - name: Checkout tiledb-rs @@ -96,9 +106,6 @@ jobs: run: cargo install cargo-expand - name: Install TileDB uses: ./.github/actions/install-tiledb - with: - version: "main" - linkage: "dynamic" - name: Build API Coverage Tool run: cd tools/api-coverage && cargo build - name: Calculate Coverage diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..8b5574f0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,53 @@ +name: Nightly CI +on: + workflow_dispatch: + push: + branches: + - main + - "release-*" + tags: + - "*" + +jobs: + run: + name: "Prepare: ${{ matrix.os }}" + strategy: + matrix: + os: + - "ubuntu-latest" + - "linux-arm64-ubuntu24" + - "macos-13" + - "macos-latest" + runs-on: ${{ matrix.os }} + steps: + - name: Checkout tiledb-rs + uses: actions/checkout@v4 + - name: Install TileDB + uses: ./.github/actions/install-tiledb + - name: Install Rust ${{ matrix.rust }} + uses: dtolnay/rust-toolchain@stable + with: + components: clippy, rustfmt + - name: Check Formatting + run: cargo fmt --quiet --check + - name: Lint + run: cargo clippy --all-targets --all-features -- -Dwarnings + - name: Build + run: cargo build --all-targets --all-features + - name: Test + run: cargo test --all-targets --all-features + + create_issue_on_fail: + permissions: + issues: write + runs-on: ubuntu-latest + needs: run + if: failure() || cancelled() + steps: + - uses: actions/checkout@v3 + - name: Create Issue on Failure + uses: TileDB-Inc/github-actions/open-issue@main + with: + name: Release Workflow Failure + label: release-failure + assignee: davisp,rroelke diff --git a/Cargo.lock b/Cargo.lock index 392c7e4e..c56c5913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1806,7 +1806,7 @@ dependencies = [ "anyhow", "arrow", "cells", - "itertools 0.13.0", + "itertools 0.12.1", "num-traits", "paste", "proptest", @@ -1842,7 +1842,7 @@ dependencies = [ name = "tiledb-pod" version = "0.1.0" dependencies = [ - "itertools 0.13.0", + "itertools 0.12.1", "num-traits", "proptest", "serde", diff --git a/Cargo.toml b/Cargo.toml index 9da06854..9f987b2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,34 +31,37 @@ edition = "2021" rust-version = "1.80" version = "0.1.0" +[workspace.metadata.libtiledb] +version = "main" + [workspace.dependencies] anyhow = "1.0" armerge = "2" arrow = { version = "52.0.0", features = ["prettyprint"] } -arrow-schema = { version = "52.0.0" } +arrow-schema = "52.0.0" bindgen = "0.70" -cells = { path = "test-utils/cells", version = "0.1.0" } +cells = { path = "test-utils/cells" } cmake = "0.1" itertools = "0" num-traits = "0.2" paste = "1.0" -proptest = { version = "1.0.0" } +pkg-config = "0.3.30" +proptest = "1.0.0" regex = "1" serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["float_roundtrip"] } -signal = { path = "test-utils/signal", version = "0.1.0" } -strategy-ext = { path = "test-utils/strategy-ext", version = "0.1.0" } +signal = { path = "test-utils/signal" } +strategy-ext = { path = "test-utils/strategy-ext" } tempfile = { version = "3" } thiserror = { version = "1" } -tiledb-api = { path = "tiledb/api", version = "0.1.0" } -tiledb-common = { path = "tiledb/common", version = "0.1.0" } -tiledb-pod = { path = "tiledb/pod", version = "0.1.0" } -tiledb-proc-macro = { path = "tiledb/proc-macro", version = "0.1.0" } -tiledb-proptest-config = { path = "test-utils/proptest-config", version = "0.1.0" } -tiledb-sys = { path = "tiledb/sys", version = "0.1.0" } -tiledb-sys-cfg = { path = "tiledb/sys-cfg", version = "0.1.0" } -tiledb-sys-defs = { path = "tiledb/sys-defs", version = "0.1.0" } -tiledb-test-utils = { path = "tiledb/test-utils", version = "0.1.0" } -tiledb-utils = { path = "tiledb/utils", version = "0.1.0" } -pkg-config = "0.3.30" -uri = { path = "test-utils/uri", version = "0.1.0" } +tiledb-api = { path = "tiledb/api" } +tiledb-common = { path = "tiledb/common" } +tiledb-pod = { path = "tiledb/pod" } +tiledb-proc-macro = { path = "tiledb/proc-macro" } +tiledb-proptest-config = { path = "test-utils/proptest-config" } +tiledb-sys = { path = "tiledb/sys" } +tiledb-sys-cfg = { path = "tiledb/sys-cfg" } +tiledb-sys-defs = { path = "tiledb/sys-defs" } +tiledb-test-utils = { path = "tiledb/test-utils" } +tiledb-utils = { path = "tiledb/utils" } +uri = { path = "test-utils/uri" } diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 00000000..6fe3f056 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,60 @@ +# How to Create a Release + +This document describes the process for creating a release of tiledb-rs. There +are two main workflows: major/minor releases and patch releases. The two are +basically identical other than patch releases skip a few extra maintenance +steps for the major/minor release types. + +## Release Types + +Given the semantic version `x.y.z`, if `x` or `y` have changed, you're working +on a major/minor release. If only `z` has chagned, then its a patch release +which just means you get to skip a few chore steps. + +## Required Tooling + +- [Git Cliff](https://git-cliff.org/) +- [GitHub CLI](https://cli.github.com/) + +## Preparing a Major or Minor Release + +1. Create a new `release-x.y` branch +2. Perform any maintenance actions +3. Run `./scripts/make-release.sh` + +### 1. Create a new `release-x.y` Branch + +```bash +$ git checkout -b release-0.1 origin/main +``` + +### 2. Perform any maintenance actions + +This section is a work in progress. So far the following steps should be +manually verified: + +1. Ensure that the `workspace.metadata.libtiledb.version` key is correct in `Cargo.toml` +2. Something something, check MSVR maybe? + +### 3. Tag the Release + +The following command will perform four major actions: + +1. Use `git cliff` to generate the release CHANGELOG +2. Open your editor to view the change log before creating the tag +3. Create and push the tag to Github +4. Create the GitHub release using the newly created tag + +```bash +$ ./scripts/make-release.sh x.y.z +``` + +## Preparing a Patch Release + +Preparing a patch release should just be a matter of running `make-release.sh` +on the release branch. + +```bash +$ git checkout release-x.y +$ ./scripts/make-release.sh x.y.z +``` diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 00000000..2a13b831 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,91 @@ +# Lightly edited from the default cliff.toml +# +# git-cliff ~ default configuration file +# https://git-cliff.org/docs/configuration +# +# Lines starting with "#" are comments. +# Configuration options are organized into tables and keys. +# See documentation for more information on available options. + +[changelog] +# template for the changelog header +# header = "" + +# template for the changelog body +# https://keats.github.io/tera/docs/#introduction +body = """tiledb-rs {{ version }} + +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | striptags | trim | upper_first }} + {% for commit in commits %} + - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ + {% if commit.breaking %}[**breaking**] {% endif %}\ + {{ commit.message | split(pat="\n") | first | upper_first | trim }}\ + {% endfor %} +{% endfor %}\n +""" +# template for the changelog footer +footer = """ + +""" +# remove the leading and trailing s +trim = true +# postprocessors +postprocessors = [ + # Update `` references + { pattern = '', replace = "https://github.com/TileDB-Inc/tiledb-rs" }, +] +# render body even when there are no releases to process +# render_always = true +# output file path +# output = "test.md" + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = false +# process each line of a commit as an individual commit +split_commits = false + +commit_preprocessors = [ + # Replace issue numbers + { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))" }, + # Strip Shortcut references + { pattern = '\[[sS][cC].\d+\]', replace = "" }, + # Check spelling of the commit with https://github.com/crate-ci/typos + # If the spelling is incorrect, it will be automatically fixed. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, +] # regex for preprocessing the commit messages + +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "๐Ÿš€ Features" }, + { message = "^fix", group = "๐Ÿ› Bug Fixes" }, + { message = "^doc", group = "๐Ÿ“š Documentation" }, + { message = "^perf", group = "โšก Performance" }, + { message = "^refactor", group = "๐Ÿšœ Refactor" }, + { message = "^style", group = "๐ŸŽจ Styling" }, + { message = "^test", group = "๐Ÿงช Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore\\(deps.*\\)", skip = true }, + { message = "^chore\\(pr\\)", skip = true }, + { message = "^chore\\(pull\\)", skip = true }, + { message = "^chore|^ci", group = "โš™๏ธ Miscellaneous Tasks" }, + { body = ".*security", group = "๐Ÿ›ก๏ธ Security" }, + { message = "^revert", group = "โ—€๏ธ Revert" }, + { message = ".*", group = "๐Ÿ’ผ Other" }, +] +# filter out the commits that are not matched by commit parsers +filter_commits = false +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "oldest" +# Ignore nightlies and nightly-libtiledb tags +ignore_tags = "nightlies|nightly-libtiledb" diff --git a/scripts/make-release.sh b/scripts/make-release.sh new file mode 100755 index 00000000..0578f0fb --- /dev/null +++ b/scripts/make-release.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +NOTES=$(git cliff --unreleased --tag $1) +git tag -a --cleanup verbatim -e -m "$NOTES" $1 +git push origin $1 +gh release create $1 --verify-tag --notes "$NOTES"