Skip to content

chore(deps): bump tokio from 1.50.0 to 1.51.1 #93

chore(deps): bump tokio from 1.50.0 to 1.51.1

chore(deps): bump tokio from 1.50.0 to 1.51.1 #93

Workflow file for this run

# CI — Checks, Build, Sign, Release
#
# Branch-aware: same workflow on develop and main.
# develop → alpha channel (forestage-a), alpha pre-release
# main → stable channel (forestage), stable pre-release
# Tagged releases (v*) are handled by release.yml.
name: CI
on:
push:
branches: [develop, main]
paths-ignore:
- '*.md'
- 'docs/**'
- 'LICENSE'
- 'CREDITS.md'
- '.gitignore'
- 'sources.toml'
- '_kos/**'
- '.github/workflows/release.yml'
- '.github/workflows/release-verify.yml'
pull_request:
branches: [develop, main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
jobs:
# ── Branch config ─────────────────────────────────────────────────────
# Derive channel-specific values from the branch name.
# All downstream jobs reference these outputs.
config:
name: Config
runs-on: ubuntu-latest
outputs:
is_alpha: ${{ steps.cfg.outputs.is_alpha }}
channel: ${{ steps.cfg.outputs.channel }}
binary_prefix: ${{ steps.cfg.outputs.binary_prefix }}
tag_prefix: ${{ steps.cfg.outputs.tag_prefix }}
release_title: ${{ steps.cfg.outputs.release_title }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- name: Set config from branch
id: cfg
run: |
if [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then
echo "is_alpha=true" >> "$GITHUB_OUTPUT"
echo "channel=alpha" >> "$GITHUB_OUTPUT"
echo "binary_prefix=forestage-a" >> "$GITHUB_OUTPUT"
echo "tag_prefix=alpha" >> "$GITHUB_OUTPUT"
echo "release_title=Alpha" >> "$GITHUB_OUTPUT"
else
echo "is_alpha=false" >> "$GITHUB_OUTPUT"
echo "channel=stable" >> "$GITHUB_OUTPUT"
echo "binary_prefix=forestage" >> "$GITHUB_OUTPUT"
echo "tag_prefix=stable" >> "$GITHUB_OUTPUT"
echo "release_title=Stable" >> "$GITHUB_OUTPUT"
fi
# ── Checks ────────────────────────────────────────────────────────────
check-fmt:
name: Rustfmt
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 1
- uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly
with:
toolchain: nightly
components: rustfmt
- uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
with:
cache-on-failure: true
- run: cargo +nightly fmt --all -- --check
check-clippy:
name: Clippy
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 1
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
toolchain: stable
components: clippy
- uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
with:
cache-on-failure: true
- run: cargo clippy --all-targets --all-features -- -D warnings
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 1
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
with:
cache-on-failure: true
- run: cargo test --all-targets
deny:
name: Cargo Deny
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 1
- uses: EmbarkStudios/cargo-deny-action@82eb9f621fbc699dd0918f3ea06864c14cc84246 # v2
with:
command: check advisories licenses bans
# ── Build ─────────────────────────────────────────────────────────────
build:
name: Build (${{ matrix.target }})
needs: [config, check-fmt, check-clippy, test, deny]
if: github.event_name == 'push'
strategy:
matrix:
include:
- target: aarch64-apple-darwin
os: macos-latest
artifact_name: forestage-darwin-arm64
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
artifact_name: forestage-linux-amd64
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04-arm
artifact_name: forestage-linux-arm64
runs-on: ${{ matrix.os }}
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
fetch-depth: 1
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
toolchain: stable
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2
with:
cache-on-failure: true
- name: Extract version
id: version
run: |
VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
TAG="${{ needs.config.outputs.tag_prefix }}-$(date -u +%Y%m%d-%H%M%S)-$(echo ${{ github.sha }} | head -c 7)"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Build binary
env:
FORESTAGE_CHANNEL: ${{ needs.config.outputs.channel }}
FORESTAGE_TAG: ${{ steps.version.outputs.tag }}
run: |
cargo build --release --target ${{ matrix.target }}
# Derive the output binary name from the artifact name and binary prefix
OUTPUT=$(echo "${{ matrix.artifact_name }}" | sed "s/forestage/${{ needs.config.outputs.binary_prefix }}/")
cp target/${{ matrix.target }}/release/forestage "$OUTPUT"
- name: Verify binary
run: |
OUTPUT=$(echo "${{ matrix.artifact_name }}" | sed "s/forestage/${{ needs.config.outputs.binary_prefix }}/")
./"$OUTPUT" --version
- name: Upload artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with:
name: binaries-${{ matrix.artifact_name }}
path: ${{ needs.config.outputs.binary_prefix }}-*
# ── Sign & Notarize ───────────────────────────────────────────────────
sign-and-notarize:
name: Sign & Notarize
needs: [config, build]
if: vars.SIGNING_ENABLED == 'true'
permissions:
contents: write
environment: release
strategy:
matrix:
arch: [arm64]
runs-on: macos-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Download binaries
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: binaries-forestage-darwin-${{ matrix.arch }}
- name: Import certificates
env:
APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_INSTALLER_CERTIFICATE_P12: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_P12 }}
APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
run: |
security create-keychain -p "" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "" build.keychain
echo "$APPLE_CERTIFICATE_P12" | base64 --decode > cert.p12
security import cert.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
rm cert.p12
echo "$APPLE_INSTALLER_CERTIFICATE_P12" | base64 --decode > installer-cert.p12
security import installer-cert.p12 -k build.keychain -P "$APPLE_INSTALLER_CERTIFICATE_PASSWORD" -T /usr/bin/pkgbuild -T /usr/bin/productbuild -T /usr/bin/productsign
rm installer-cert.p12
curl -sfo /tmp/DeveloperIDG2CA.cer https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer
security add-certificates -k build.keychain /tmp/DeveloperIDG2CA.cer
rm /tmp/DeveloperIDG2CA.cer
security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
- name: Sign binary
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
BINARY: ${{ needs.config.outputs.binary_prefix }}-darwin-${{ matrix.arch }}
run: |
codesign --force --options runtime \
--sign "$APPLE_SIGNING_IDENTITY" \
--timestamp \
"$BINARY"
- name: Verify signature
run: codesign --verify --deep --strict ${{ needs.config.outputs.binary_prefix }}-darwin-${{ matrix.arch }}
- name: Build app bundle
run: |
VERSION="${{ needs.build.outputs.version }}"
chmod +x scripts/create-app.sh
./scripts/create-app.sh ${{ needs.config.outputs.binary_prefix }}-darwin-${{ matrix.arch }} "$VERSION" .
mv Forestage.app Forestage-${{ matrix.arch }}.app
- name: Sign app bundle
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
codesign --force --deep --options runtime \
--sign "$APPLE_SIGNING_IDENTITY" \
--timestamp \
Forestage-${{ matrix.arch }}.app
- name: Build dmg
run: |
VERSION="${{ needs.build.outputs.version }}"
chmod +x scripts/create-dmg.sh
./scripts/create-dmg.sh Forestage-${{ matrix.arch }}.app "$VERSION" forestage-${{ matrix.arch }}.dmg
- name: Build pkg
env:
APPLE_INSTALLER_IDENTITY: ${{ secrets.APPLE_INSTALLER_IDENTITY }}
run: |
if ! security find-identity -v build.keychain | grep -q "$APPLE_INSTALLER_IDENTITY"; then
echo "::error::APPLE_INSTALLER_IDENTITY not found in keychain"
security find-identity -v build.keychain
exit 1
fi
VERSION="${{ needs.build.outputs.version }}"
chmod +x scripts/create-pkg.sh
./scripts/create-pkg.sh ${{ needs.config.outputs.binary_prefix }}-darwin-${{ matrix.arch }} "$VERSION" "$APPLE_INSTALLER_IDENTITY" forestage-${{ matrix.arch }}.pkg
- name: Notarize and staple
env:
APPLE_NOTARIZATION_APPLE_ID: ${{ secrets.APPLE_NOTARIZATION_APPLE_ID }}
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
APPLE_NOTARIZATION_TEAM_ID: ${{ secrets.APPLE_NOTARIZATION_TEAM_ID }}
run: |
for ARTIFACT in forestage-${{ matrix.arch }}.pkg forestage-${{ matrix.arch }}.dmg; do
echo "Notarizing $ARTIFACT..."
xcrun notarytool submit "$ARTIFACT" \
--apple-id "$APPLE_NOTARIZATION_APPLE_ID" \
--password "$APPLE_NOTARIZATION_PASSWORD" \
--team-id "$APPLE_NOTARIZATION_TEAM_ID" \
--wait --timeout 14400
xcrun stapler staple "$ARTIFACT"
done
- name: Upload signed artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with:
name: signed-binaries-darwin-${{ matrix.arch }}
path: |
${{ needs.config.outputs.binary_prefix }}-darwin-${{ matrix.arch }}
forestage-${{ matrix.arch }}.pkg
forestage-${{ matrix.arch }}.dmg
retention-days: 14
- name: Cleanup keychain
if: always()
run: security delete-keychain build.keychain || true
# ── Release ───────────────────────────────────────────────────────────
create-release:
name: Create ${{ needs.config.outputs.release_title }} Release
needs: [config, build, sign-and-notarize]
if: |
always() &&
needs.build.result == 'success' &&
(needs.sign-and-notarize.result == 'success' || needs.sign-and-notarize.result == 'skipped')
permissions:
contents: write
environment: release
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- name: Download macOS arm64
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: ${{ needs.sign-and-notarize.result == 'success' && 'signed-binaries-darwin-arm64' || 'binaries-forestage-darwin-arm64' }}
path: dist/
- name: Download Linux amd64
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: binaries-forestage-linux-amd64
path: dist/
- name: Download Linux arm64
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: binaries-forestage-linux-arm64
path: dist/
- name: List release files
run: ls -la dist/
- name: Create pre-release
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="${{ needs.build.outputs.tag }}"
TITLE="${{ needs.config.outputs.release_title }}"
PREFIX="${{ needs.config.outputs.binary_prefix }}"
gh release create "$TAG" \
--repo "${{ github.repository }}" \
--prerelease \
--title "$TITLE: $TAG" \
--notes "$(cat <<NOTES
Automated $TITLE release.
**Version:** ${{ needs.build.outputs.version }}
**Commit:** ${{ github.sha }}
**Branch:** ${{ github.ref_name }}
**Built with:** Rust (cargo)
**Signed:** ${{ needs.sign-and-notarize.result == 'success' && 'Yes (Apple Developer ID)' || 'No (unsigned)' }}
**Binaries:**
- \`${PREFIX}-darwin-arm64\` — macOS Apple Silicon
- \`${PREFIX}-linux-amd64\` — Linux x86_64
- \`${PREFIX}-linux-arm64\` — Linux ARM64
NOTES
)" \
dist/*
- name: Clean old pre-releases (keep 30)
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release list --repo "${{ github.repository }}" \
--json tagName,isPrerelease \
--jq '[.[] | select(.isPrerelease)] | sort_by(.tagName) | reverse | .[30:] | .[].tagName' \
| while read -r tag; do
echo "Deleting old pre-release: $tag"
gh release delete "$tag" --repo "${{ github.repository }}" --yes --cleanup-tag
done
# ── Homebrew (alpha only) ─────────────────────────────────────────────
update-homebrew:
name: Update Homebrew Tap
needs: [config, build, sign-and-notarize, create-release]
if: needs.create-release.result == 'success' && needs.sign-and-notarize.result == 'success' && needs.config.outputs.is_alpha == 'true'
permissions:
contents: write
environment: release
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Download signed darwin binaries
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: signed-binaries-darwin-arm64
path: dist/
- name: Update Homebrew formula
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
TAG="${{ needs.build.outputs.tag }}"
VERSION="${{ needs.build.outputs.version }}"
SHA256_ARM64=$(shasum -a 256 dist/forestage-a-darwin-arm64 | cut -d' ' -f1)
git clone "https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/arcavenae/homebrew-tap.git" homebrew-tap-repo
cd homebrew-tap-repo
mkdir -p Formula
cp ../Formula/forestage-a.rb Formula/forestage-a.rb
sed -i "s/VERSION_PLACEHOLDER/$TAG/g" Formula/forestage-a.rb
sed -i "s/TAG_PLACEHOLDER/$TAG/g" Formula/forestage-a.rb
sed -i "s/SHA256_ARM64_PLACEHOLDER/$SHA256_ARM64/g" Formula/forestage-a.rb
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/forestage-a.rb
git diff --cached --quiet || git commit -m "Update forestage-a to $TAG"
git push