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
16 changes: 7 additions & 9 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
name: Publish to crates.io

on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-*'
release:
types: [published]
workflow_dispatch:
inputs:
dry_run:
Expand Down Expand Up @@ -49,7 +47,7 @@ jobs:
needs: test
runs-on: ubuntu-latest
if: >-
github.event_name == 'push' ||
github.event_name == 'release' ||
(github.event_name == 'workflow_dispatch' &&
(github.event.inputs.crate == 'all' || github.event.inputs.crate == 'fetchkit'))
steps:
Expand All @@ -65,7 +63,7 @@ jobs:
run: cargo publish -p fetchkit --dry-run

- name: Publish fetchkit
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
run: cargo publish -p fetchkit
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
Expand All @@ -75,7 +73,7 @@ jobs:
needs: [test, publish-fetchkit]
runs-on: ubuntu-latest
if: >-
github.event_name == 'push' ||
github.event_name == 'release' ||
(github.event_name == 'workflow_dispatch' &&
(github.event.inputs.crate == 'all' || github.event.inputs.crate == 'fetchkit-cli'))
steps:
Expand All @@ -85,7 +83,7 @@ jobs:

# Wait for crates.io index to update after fetchkit publish
- name: Wait for crates.io index
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
run: sleep 30

- name: Verify crate can be packaged
Expand All @@ -96,7 +94,7 @@ jobs:
run: cargo publish -p fetchkit-cli --dry-run

- name: Publish fetchkit-cli
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
run: cargo publish -p fetchkit-cli
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
90 changes: 90 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Release

on:
push:
branches:
- main

jobs:
release:
runs-on: ubuntu-latest
# Only run if commit message matches release pattern
if: ${{ startsWith(github.event.head_commit.message, 'chore(release): prepare v') }}

permissions:
contents: write

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Extract version from commit message
id: version
run: |
# Extract version from commit message like "chore(release): prepare v0.1.0"
VERSION=$(echo "${{ github.event.head_commit.message }}" | grep -oP 'prepare v\K[0-9]+\.[0-9]+\.[0-9]+')
if [ -z "$VERSION" ]; then
echo "::error::Could not extract version from commit message"
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"

- name: Check if tag already exists
id: check_tag
run: |
if git rev-parse "v${{ steps.version.outputs.version }}" >/dev/null 2>&1; then
echo "::error::Tag v${{ steps.version.outputs.version }} already exists"
exit 1
fi
echo "Tag does not exist, proceeding..."

- name: Verify Cargo.toml version matches
run: |
CARGO_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
if [ "$CARGO_VERSION" != "${{ steps.version.outputs.version }}" ]; then
echo "::error::Cargo.toml version ($CARGO_VERSION) does not match release version (${{ steps.version.outputs.version }})"
exit 1
fi
echo "Cargo.toml version matches: $CARGO_VERSION"

- name: Extract release notes from CHANGELOG.md
id: changelog
run: |
VERSION="${{ steps.version.outputs.version }}"

# Extract the section for this version from CHANGELOG.md
# Matches from "## [X.Y.Z]" until the next "## [" or end of significant content
NOTES=$(awk -v ver="$VERSION" '
/^## \[/ {
if (found) exit
if (index($0, "[" ver "]")) found=1
next
}
found && /^## \[/ { exit }
found { print }
' CHANGELOG.md)

if [ -z "$NOTES" ]; then
echo "::warning::No changelog entry found for version $VERSION"
NOTES="Release v$VERSION"
fi

# Write to file to preserve formatting
echo "$NOTES" > release_notes.md
echo "Release notes extracted:"
cat release_notes.md

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "v${{ steps.version.outputs.version }}" \
--title "v${{ steps.version.outputs.version }}" \
--notes-file release_notes.md \
--target "${{ github.sha }}"

echo "Created release v${{ steps.version.outputs.version }}"
32 changes: 11 additions & 21 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,33 +92,23 @@ specs/ # Feature specifications
- Clippy runs with `-D warnings` (warnings are errors)
- Doc builds must not have warnings

### Publishing to crates.io
### Releasing

Workflow: `.github/workflows/publish.yml`
See `docs/release-process.md` for full release process documentation.

Triggers:
- Push version tag: `v*.*.*` or `v*.*.*-*` (e.g., `v0.1.0`, `v0.2.0-beta.1`)
- Manual workflow dispatch with dry-run option
Quick summary:
1. Human asks agent: "Create release v0.2.0"
2. Agent updates CHANGELOG.md, Cargo.toml version, creates PR
3. Human reviews and merges PR to main
4. CI creates GitHub Release (release.yml)
5. CI publishes to crates.io (publish.yml)

Process:
1. Runs tests, fmt check, and clippy
2. Publishes `fetchkit` library first
3. Waits for crates.io index update
4. Publishes `fetchkit-cli`
Workflows:
- `.github/workflows/release.yml` - Creates GitHub Release on merge
- `.github/workflows/publish.yml` - Publishes to crates.io on GitHub Release

Requirements:
- `CARGO_REGISTRY_TOKEN` secret must be configured in repo settings
- Crate metadata (name, version, description, license, repository) in Cargo.toml

Release steps:
```bash
# 1. Update version in Cargo.toml (workspace level)
# 2. Commit version bump
git commit -am "chore: bump version to 0.2.0"
# 3. Create and push tag
git tag v0.2.0
git push origin main --tags
```

Note: `fetchkit-python` is not published to crates.io (uses PyPI distribution instead).

Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### What's Changed

- feat: add pluggable fetcher system for URL-specific handling ([#9](https://github.com/everruns/fetchkit/pull/9)) by @chaliy
- docs: add LangChain example for MCP integration ([#8](https://github.com/everruns/fetchkit/pull/8)) by @chaliy
- refactor(cli): unified md-first output format ([#7](https://github.com/everruns/fetchkit/pull/7)) by @chaliy
- docs: clarify test classification in AGENTS.md ([#6](https://github.com/everruns/fetchkit/pull/6)) by @chaliy
- docs: add cloud agent env and complete AGENTS.md placeholders ([#5](https://github.com/everruns/fetchkit/pull/5)) by @chaliy
- refactor: rename project from webfetch to fetchkit ([#4](https://github.com/everruns/fetchkit/pull/4)) by @chaliy
- docs: add comprehensive README with installation and usage guide ([#3](https://github.com/everruns/fetchkit/pull/3)) by @chaliy
- feat: implement webfetch library, CLI, MCP server, and Python bindings ([#1](https://github.com/everruns/fetchkit/pull/1)) by @chaliy
- feat: add initial webfetch spec and guidance by @chaliy

[Unreleased]: https://github.com/everruns/fetchkit/compare/HEAD...HEAD
Loading