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
122 changes: 122 additions & 0 deletions .github/workflows/vale-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Release Vale package

on:
push:
branches: [main]
paths:
- "vale/LanceDB/meta.json"
- ".github/workflows/vale-release.yml"
pull_request:
paths:
- "vale/**"
- ".github/workflows/vale-release.yml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: vale-package-${{ github.ref }}
queue: max
cancel-in-progress: false
Comment thread
brendanclement marked this conversation as resolved.

jobs:
package:
runs-on: ubuntu-24.04
outputs:
tag: ${{ steps.package.outputs.tag }}
exists: ${{ steps.package.outputs.exists }}
env:
VALE_VERSION: 3.24.0
VALE_SHA256: 867534ddb678abca7f214bc4706ead0922bd5252ffe8035fc227013f66c8b214
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- name: Install Vale
run: |
archive="vale_${VALE_VERSION}_Linux_64-bit.tar.gz"
curl --fail --location --silent --show-error --output "$RUNNER_TEMP/$archive" \
"https://github.com/vale-cli/vale/releases/download/v${VALE_VERSION}/$archive"
echo "${VALE_SHA256} $RUNNER_TEMP/$archive" | sha256sum --check
tar -xzf "$RUNNER_TEMP/$archive" -C "$RUNNER_TEMP" vale
echo "$RUNNER_TEMP" >> "$GITHUB_PATH"

- name: Test the Vale rules
working-directory: vale/LanceDB
run: vale test --coverage styles ../tests

- name: Build and check the package
id: package
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
version="$(jq -er '.version | select(type == "string")' vale/LanceDB/meta.json)"
[[ "$version" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]
tag="vale-lancedb-v$version"
revision=HEAD
exists=false
status=0
git ls-remote --exit-code --tags origin "refs/tags/$tag" > /dev/null || status=$?
case "$status" in
0)
git fetch --no-tags origin "refs/tags/$tag"
revision="$(git rev-parse 'FETCH_HEAD^{commit}')"
if [[ "$(git rev-parse "$revision:vale/LanceDB")" != "$(git rev-parse HEAD:vale/LanceDB)" ]]; then
echo "$tag has different package contents. Bump the version." >&2
exit 1
fi
[[ "$(gh release view "$tag" --repo "$GITHUB_REPOSITORY" --json isDraft,isPrerelease --jq '.isDraft or .isPrerelease')" == false ]]
gh release download "$tag" --repo "$GITHUB_REPOSITORY" --pattern LanceDB.zip --dir "$RUNNER_TEMP/published"
exists=true
;;
2) ;;
*) echo "Could not check existing tags; stopping." >&2; exit "$status" ;;
esac
# Build from the verified source commit.
git archive --format=zip --prefix=LanceDB/ \
--mtime="$(git show -s --format=%cI "$revision")" \
--output="$RUNNER_TEMP/LanceDB.zip" "$revision:vale/LanceDB"
if [[ "$exists" == true ]]; then
# ZIP timestamps can vary across platforms; compare the actual files.
unzip -q "$RUNNER_TEMP/LanceDB.zip" -d "$RUNNER_TEMP/built-files"
unzip -q "$RUNNER_TEMP/published/LanceDB.zip" -d "$RUNNER_TEMP/published-files"
diff -r "$RUNNER_TEMP/built-files" "$RUNNER_TEMP/published-files"
echo "Published package matches; skipping publication."
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "exists=$exists" >> "$GITHUB_OUTPUT"

- uses: actions/upload-artifact@v4
if: steps.package.outputs.exists != 'true'
with:
name: vale-package
path: ${{ runner.temp }}/LanceDB.zip
if-no-files-found: error

publish:
needs: package
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' && needs.package.outputs.exists != 'true'
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
name: vale-package
path: ${{ runner.temp }}/vale-package

- name: Publish a new version
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ needs.package.outputs.tag }}
run: |
# Atomically reserve the tag; never reuse a tag created by another run.
gh api --method POST "repos/$GITHUB_REPOSITORY/git/refs" \
-f "ref=refs/tags/$RELEASE_TAG" -f "sha=$GITHUB_SHA"
gh release create "$RELEASE_TAG" "$RUNNER_TEMP/vale-package/LanceDB.zip" \
--repo "$GITHUB_REPOSITORY" --verify-tag \
--title "$RELEASE_TAG" --latest=false \
--notes "Shared LanceDB Vale rules. Source commit: $GITHUB_SHA. This release does not publish the documentation site."
44 changes: 34 additions & 10 deletions vale/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,37 @@ keeps finding, with a case that it catches and a case that it leaves alone.

## Release

Consumers pin a release by URL, so a change reaches them only when their URL
moves. After a change merges, bump `version` in `LanceDB/meta.json`, then build
the archive from the merged commit and attach it to a release. Archiving a
directory stamps its files with the current time, so set `--mtime` to the
commit time to get the same archive every time:

```bash
git archive --format=zip --prefix=LanceDB/ --mtime="$(git log -1 --format=%cI <commit>)" -o LanceDB.zip <commit>:vale/LanceDB
gh release create vale-lancedb-v<version> LanceDB.zip --target <commit>
```
Consumers pin a package release by URL. To release updated rules, change
`version` in `LanceDB/meta.json` in the same pull request as the package changes.
Use a new stable `major.minor.patch` version for each release.

When that version change merges into `main`, the **Release Vale package**
workflow tests the package, builds `LanceDB.zip` from that exact commit and
publishes `vale-lancedb-v<version>`. The archive uses the commit timestamp so
repeated builds from that commit on the same toolchain produce identical bytes. No local ZIP build
or personal access token is needed; the workflow uses GitHub's repository token.

Pull requests run the existing Vale rule tests on Ubuntu, then build and check
the archive without publishing. Only a successful run on `main` can enter the
separate publishing job with write permission.

Adding or changing the release workflow also starts it on `main`. The workflow can be started from the Actions page on `main` to
retry a failure. Before publishing, it checks for the version's tag and release:

- If neither exists, it publishes the new version.
- If both exist, it verifies that the tagged package source matches the current
package, rebuilds it, and compares the unpacked files with the published
download. Matching files skip publication; ZIP timestamps are ignored.
- Different contents, a missing or incomplete asset, a draft release, or a tag
without a release stop the run. Nothing is replaced or deleted. Inspect the
failure; use a new version for changed rules.

The manually published `0.1.0` package is already available. Merging this
workflow verifies that package and skips publication if it matches.

After publication, update the release URL in each consumer's `.vale.ini` and
check its CI before merging. Consumer updates remain explicit; publishing a
new package does not silently change another repository's rules.

This workflow publishes only the Vale package. It does not publish staging or
production documentation, deploy Gatekeeper, or update consumer repositories.
Loading