From c2995cff04a1c2b9202bc29eca66238568d62c6d Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 20 Aug 2025 21:25:24 +0200 Subject: [PATCH 01/10] decouple versions again --- Cargo.toml | 3 +-- audio/Cargo.toml | 2 +- connect/Cargo.toml | 2 +- core/Cargo.toml | 2 +- discovery/Cargo.toml | 2 +- metadata/Cargo.toml | 2 +- oauth/Cargo.toml | 2 +- playback/Cargo.toml | 2 +- protocol/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9ac28ffbf..61bc68ec0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors.workspace = true license.workspace = true @@ -29,7 +29,6 @@ include = [ ] [workspace.package] -version = "0.7.0" rust-version = "1.85" authors = ["Librespot Org"] license = "MIT" diff --git a/audio/Cargo.toml b/audio/Cargo.toml index 0e0daa343..069d40476 100644 --- a/audio/Cargo.toml +++ b/audio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-audio" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Paul Lietar "] license.workspace = true diff --git a/connect/Cargo.toml b/connect/Cargo.toml index b5b519b04..0b5541c23 100644 --- a/connect/Cargo.toml +++ b/connect/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-connect" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Paul Lietar "] license.workspace = true diff --git a/core/Cargo.toml b/core/Cargo.toml index 8f79fd566..0f4f5ec39 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-core" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Paul Lietar "] license.workspace = true diff --git a/discovery/Cargo.toml b/discovery/Cargo.toml index 2e754e846..d133d42c2 100644 --- a/discovery/Cargo.toml +++ b/discovery/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-discovery" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Paul Lietar "] license.workspace = true diff --git a/metadata/Cargo.toml b/metadata/Cargo.toml index 01b0ec0bf..18831ccdc 100644 --- a/metadata/Cargo.toml +++ b/metadata/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-metadata" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Paul Lietar "] license.workspace = true diff --git a/oauth/Cargo.toml b/oauth/Cargo.toml index 31d58df0e..6f6d9b1d6 100644 --- a/oauth/Cargo.toml +++ b/oauth/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-oauth" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Nick Steel "] license.workspace = true diff --git a/playback/Cargo.toml b/playback/Cargo.toml index cb39541d0..54d3f6fe1 100644 --- a/playback/Cargo.toml +++ b/playback/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-playback" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Sasha Hilton "] license.workspace = true diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml index 1d880e4b8..2d3e3b13a 100644 --- a/protocol/Cargo.toml +++ b/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "librespot-protocol" -version.workspace = true +version = "0.7.0" rust-version.workspace = true authors = ["Paul LiƩtar "] license.workspace = true From 08a9efa5b860632e51d31f63f69b0df7f7559ac0 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 20 Aug 2025 18:57:29 +0200 Subject: [PATCH 02/10] add prepare-release.yml --- .github/example/prepare-release.event | 6 +++ .github/scripts/bump-versions.sh | 69 +++++++++++++++++++++++++++ .github/workflows/prepare-release.yml | 57 ++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 .github/example/prepare-release.event create mode 100755 .github/scripts/bump-versions.sh create mode 100644 .github/workflows/prepare-release.yml diff --git a/.github/example/prepare-release.event b/.github/example/prepare-release.event new file mode 100644 index 000000000..74f1822d6 --- /dev/null +++ b/.github/example/prepare-release.event @@ -0,0 +1,6 @@ +{ + "action": "workflow_dispatch", + "inputs": { + "versionBump": "minor" + } +} \ No newline at end of file diff --git a/.github/scripts/bump-versions.sh b/.github/scripts/bump-versions.sh new file mode 100755 index 000000000..4fa1379a4 --- /dev/null +++ b/.github/scripts/bump-versions.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# $FRAGMENT: see possible options https://github.com/christian-draeger/increment-semantic-version/tree/1.2.3?tab=readme-ov-file#version-fragment +if [ "$FRAGMENT" = "" ]; then + FRAGMENT=$1 +fi + +CRATES="protocol oauth core discovery audio metadata playback connect" + +if [ "$FRAGMENT" = "patch" ]; then + LAST_TAG=$(git describe --tags --abbrev=0) + AWK_CRATES=$(echo "$CRATES" | tr ' ' '|') + DIFF_CRATES=$(git diff $LAST_TAG... --stat --name-only \ + | awk '/(rs|proto)$/{print}' \ + | awk "/($AWK_CRATES)/{print}" \ + | cut -d '/' -f 1 \ + | uniq \ + | tr \\n '\ ' \ + | xargs ) + echo "upgrading the following crates: [$DIFF_CRATES]" +else + DIFF_CRATES=$CRATES + echo "upgrading all crates for consistency" +fi + +# append bin so that the version of the binary is also bumped +DIFF_CRATES="$DIFF_CRATES bin" + +# required by script as it's usually a github action +export GITHUB_OUTPUT="version.txt" +# https://github.com/christian-draeger/increment-semantic-version/tree/1.2.3 +INCREMENT_SEMVER=$(curl https://raw.githubusercontent.com/christian-draeger/increment-semantic-version/refs/tags/1.2.3/entrypoint.sh) + +for CRATE in $DIFF_CRATES ; do + if [ "$CRATE" = "bin" ]; then + TOML="./Cargo.toml" + else + TOML="./$CRATE/Cargo.toml" + fi + + FROM="$(cat $TOML | awk "/version/{print; exit}" | cut -d\" -f 2)" + + # execute script inline, extract result and remove output file + echo "$INCREMENT_SEMVER" | bash /dev/stdin $FROM $FRAGMENT + TO=$(cat $GITHUB_OUTPUT | cut -d= -f 2) + rm $GITHUB_OUTPUT + + echo "upgrading [librespot-$CRATE] from [$FROM] to [$TO]" + + # replace version in associated crate toml + sed -i "0,/$FROM/{s/$FROM/$TO/}" $TOML + + if [ "$CRATE" = "bin" ]; then + continue + fi + + # update workspace dependency in root toml + sed -i "/librespot-$CRATE/{s/$FROM/$TO/}" ./Cargo.toml + + # update related dependencies in crate + for crate in $CRATES ; do + cat $TOML | grep librespot-$crate > /dev/null + if [ $? = 0 ]; then + sed -i "/librespot-$CRATE/{s/$FROM/$TO/}" $TOML + fi + done +done + +exit 0 diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 000000000..a49d3188d --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,57 @@ +--- +# test with +# act --job bump-crate-version --eventpath ./.github/example/prepare-release.event +name: prepare release +on: + workflow_dispatch: + inputs: + versionBump: + description: "Version bump for" + required: true + type: choice + options: + - major + - minor + - patch + +jobs: + prepare-release: + name: Prepare release + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-tags: true + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Bump versions + env: + FRAGMENT: ${{ github.event.inputs.versionBump }} + run: ./.github/scripts/bump-versions.sh + + - name: Update Cargo.lock + run: cargo update --workspace + + - name: Get binary version + id: get-version + run: | + VERSION=$(cat ./Cargo.toml | awk "/version/{print; exit}" | cut -d\" -f 2) + echo VERSION=$VERSION >> ${GITHUB_OUTPUT} + + - name: Update Changelog + uses: thomaseizinger/keep-a-changelog-new-release@3.1.0 + with: + tag: v${{ steps.get-version.outputs.VERSION }} + version: ${{ steps.get-version.outputs.VERSION }} + + - name: Commit version prepare + uses: stefanzweifel/git-auto-commit-action@v6 + if: ${{ !env.ACT }} + with: + commit_message: 'Prepare for v${{ steps.get-version.outputs.VERSION }} release' + file_pattern: '*.md *.toml *.lock' From f6ac16219f33f238d564e44f7254701b035beaf7 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 27 Aug 2025 15:27:26 +0200 Subject: [PATCH 03/10] add release.yml --- .github/scripts/get-excluded-crates.sh | 49 ++++++++++++ .github/workflows/release.yml | 101 +++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100755 .github/scripts/get-excluded-crates.sh create mode 100644 .github/workflows/release.yml diff --git a/.github/scripts/get-excluded-crates.sh b/.github/scripts/get-excluded-crates.sh new file mode 100755 index 000000000..0a1fc4233 --- /dev/null +++ b/.github/scripts/get-excluded-crates.sh @@ -0,0 +1,49 @@ +CRATES="protocol oauth core discovery audio metadata playback connect" + +CURRENT_TAG=$(git describe --abbrev=0) +LAST_TAG=$(git describe --abbrev=0 $CURRENT_TAG^) + +BIN_VERSION=$(cat ./Cargo.toml | awk "/version/{print; exit}" | cut -d\" -f 2) + +SIMPLE_VERSION_REGEX="^v?([0-9]+)\.([0-9]+)\.([0-9]+)$" +if [[ $LAST_TAG =~ $SIMPLE_VERSION_REGEX ]]; then + last_major="${BASH_REMATCH[1]}" + last_minor="${BASH_REMATCH[2]}" + last_patch="${BASH_REMATCH[3]}" +else + echo "regex for tag didn't match" + exit 1 +fi + +if [[ $BIN_VERSION =~ $SIMPLE_VERSION_REGEX ]]; then + if [ "$last_major" != "${BASH_REMATCH[1]}" ] || [ "$last_minor" != "${BASH_REMATCH[2]}" ]; then + echo "[]" + exit 0 + elif [ "$last_patch" == "${BASH_REMATCH[3]}" ]; then + echo "version didn't change" + exit 1 + fi +else + echo "regex for bin version didn't match" + exit 1 +fi + +# if we go through here, we build a patch version and only want to update the crates that have changed +AWK_CRATES=$(echo "$CRATES" | tr ' ' '|') +DIFF_CRATES=$(git diff $LAST_TAG... --stat --name-only \ + | awk '/(rs|proto)$/{print}' \ + | awk "/($AWK_CRATES)/{print}" \ + | cut -d '/' -f 1 \ + | uniq \ + | tr '\n' ' ' \ + | xargs \ + | tr ' ' '|' ) + +EXCLUDED_DIFF=$(echo $CRATES \ + | tr ' ' '\n' \ + | awk "!/($DIFF_CRATES)/{print}" \ + | tr '\n' ' ' \ + | xargs \ + | sed "s/ /\" }\, { \"crate\": \"/g") + +echo "[ { \"crate\": \"$EXCLUDED_DIFF\" } ]" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..0ec749799 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,101 @@ +name: release.yml +on: + release: + types: + - created + workflow_dispatch: + +jobs: + get-excluded-crates: + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + excluded: ${{ steps.excluded-crates.outputs.EXCLUDE }} + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-tags: true + + - name: Get excluded crates + id: excluded-crates + run: | + EXCLUDE=$(./.github/scripts/get-excluded-crates.sh) + echo "excluding [$EXCLUDE]" + echo EXCLUDE=$EXCLUDE >> ${GITHUB_OUTPUT} + + publish-crates: + name: Publish crate librespot-${{ matrix.crate }} + needs: [ get-excluded-crates ] + runs-on: ubuntu-latest + permissions: + contents: read + strategy: + max-parallel: 1 # for sequential execution because the order of publishing the crates is important + matrix: + # order is important + crate: + - protocol + - oauth + - core + - discovery + - audio + - metadata + - playback + - connect + # not all crates needs to be published all the time + exclude: ${{ fromJSON(needs.get-excluded-crates.outputs.excluded) }} + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 + + - name: Install dependencies + if: ${{ contains('connect playback', matrix.crate ) }} # only install the dep when the crate requires it + run: sudo apt-get update && sudo apt-get install -y libasound2-dev + + - name: Verify librespot-${{ matrix.crate }} + run: cargo publish --package librespot-${{ matrix.crate }} --dry-run + + - name: Publish librespot-${{ matrix.crate }} + if: ${{ !env.ACT }} + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: | + if [ "${{ matrix.crate }}" = "protocol" ]; then + cargo publish --package librespot-${{ matrix.crate }} --no-verify + else + cargo publish --package librespot-${{ matrix.crate }} + fi + + publish-binary: + name: publish librespot binary + needs: [ publish-crates ] + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 + + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y libasound2-dev + + - name: Verify librespot + run: cargo publish --dry-run --allow-dirty + + - name: Publish librespot + if: ${{ !env.ACT }} + run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} From d9d67efb07d573975d5475ab99037e4ca57c1d92 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Thu, 28 Aug 2025 00:46:51 +0200 Subject: [PATCH 04/10] cleanup docs and publish.sh --- .github/workflows/build.yml | 2 - CHANGELOG.md | 12 +-- PUBLISHING.md | 55 +++++----- publish.sh | 204 ------------------------------------ 4 files changed, 28 insertions(+), 245 deletions(-) delete mode 100755 publish.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 88b1b8c56..547bd0cc1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,6 @@ name: build - "LICENSE" - "*.sh" - "**/Dockerfile*" - - "publish.sh" - "test.sh" pull_request: paths-ignore: @@ -22,7 +21,6 @@ name: build - "LICENSE" - "*.sh" - "**/Dockerfile*" - - "publish.sh" - "test.sh" schedule: # Run CI every week diff --git a/CHANGELOG.md b/CHANGELOG.md index 27bb7de8d..655c800cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,21 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added - -### Changed - -### Deprecated - -### Removed - ### Fixed - [connect] Only deletes the connect state on dealer shutdown instead on disconnecting - [core] Fixed a problem where in `spclient` where a http 411 error was thrown because the header were set wrong -### Security - ## [0.7.0] - 2025-08-24 ### Changed @@ -137,7 +127,7 @@ will be well worth it. All these changes are likely to introduce new bugs as well as some regressions. We appreciate all your testing and contributions to the repository: -https://github.com/librespot-org/librespot + ### Changed diff --git a/PUBLISHING.md b/PUBLISHING.md index 3859c90a9..3c0bb95c2 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -2,42 +2,41 @@ ## How To -Read through this paragraph in its entirety before running anything. +1. [prepare the release](#prepare-the-release) +2. [create a github-release](#creating-a-github-release) -The Bash script in the root of the project, named `publish.sh` can be used to publish a new version of librespot and its corresponding crates. the command should be used as follows from the project root: `./publish 0.1.0` from the project root, substituting the new version number that you wish to publish. *Note the lack of a v prefix on the version number. This is important, do not add one.* The v prefix is added where appropriate by the script. +### Prepare the release -Make sure that you are are starting from a clean working directory for both `dev` and `master`, completely up to date with remote and all local changes either committed and pushed or stashed. +For preparing the release a manuel workflow should be available that takes care of the common preparation. But +this can also be done manually if so desired. The workflow does: +- upgrade the version according to the targeted release (`major`, `minor`, `patch`) + - `major` and `minor` require all crates to be updated + - `patch` instead only upgrades the crates that had any changes +- updates the changelog according to Keep-A-Changelog convention +- commits and pushes the changes to remote -Note that the script will update the crates and lockfile, so in case you did not do so before, you really should to make sure none of the dependencies introduce some SemVer breaking change. Then commit so you again have a clean working directory. +### Creating a github-release -Also don't forget to update `CHANGELOG.md` with the version number, release date, and at the bottom the comparison links. +After everything is prepared for the new version. A [new release can be created](https://github.com/librespot-org/librespot/releases/new) +from the ui. The tag will not be available as it isn't set by the prepare workflow, so a new tag needs to be created. +The tag should be named like `v` where `version` is the version of the binary. -You will want to perform a dry run first: `./publish --dry-run 0.1.0`. Please make note of any errors or warnings. In particular, you may need to explicitly inform Git which remote you want to track for the `master` branch like so: `git --track origin/master` (or whatever you have called the `librespot-org` remote `master` branch). +> insert convention what the release title and release notes should be and what checkboxes to check etc. -Depending on your system the script may fail to publish the main `librespot` crate after having published all the `librespot-xyz` sub-crates. If so then make sure the working directory is committed and pushed (watch `Cargo.toml`) and then run `cargo publish` manually after `publish.sh` finished. +The release should be created as draft, which will trigger the workflow that will publish the changed crates and binary. +The workflow will: +- check if all crates needs to be published or only certain crates +- publish the crates in a specific order while excluding crates that didn't have any changes +- publish the binary -To publish the crates your GitHub account needs to be authorized on `crates.io` by `librespot-org`. First time you should run `cargo login` and follow the on-screen instructions. - -## What the script does - -This is briefly how the script works: - - - Change to branch master, pull latest version, merge development branch. - - Change to working directory. - - Change version number in all files. - - Update crates and lockfile. - - Commit and tag changes. - - Publish crates in given order. - - Push version commit and tags to master. +After the workflow was successful the version can be published. ## Notes -Publishing librespot to crates.io is a slightly convoluted affair due to the various dependencies that each package has on other local packages. The order of publising that has been found to work is as follows: - -`protocol -> core -> audio -> metadata -> playback -> connect -> librespot` - -The `protocol` package needs to be published with `cargo publish --no-verify` due to the build script modifying the source during compile time. - -Publishing can be done using the command `cargo publish` in each of the directories of the respective crate. +Publishing librespot to crates.io is a slightly convoluted affair due to the various dependencies that each package has +on other local packages. The order of publishing that has been found to work is as follows: +> `protocol -> core -> audio -> metadata -> playback -> connect -> librespot` -The script is meant to cover the standard publishing process. There are various improvements that could be made, such as adding options such as the user being able to add a changelog, though this is not the main focus, as the script is intended to be run by a CI. Feel free to improve and extend functionality, keeping in mind that it should always be possible for the script to be run in a non-interactive fashion. +The `protocol` package needs to be published with `cargo publish --no-verify` due to the build script modifying the +source during compile time. Publishing can be done using the command `cargo publish` in each of the directories of the +respective crate. diff --git a/publish.sh b/publish.sh deleted file mode 100755 index 94eedf252..000000000 --- a/publish.sh +++ /dev/null @@ -1,204 +0,0 @@ -#!/bin/bash - -SKIP_MERGE='false' -DRY_RUN='false' - -WORKINGDIR="$( cd "$(dirname "$0")" ; pwd -P )" -cd $WORKINGDIR - -# Order: dependencies first (so "librespot" using everything before it goes last) -crates=( "protocol" "oauth" "core" "discovery" "audio" "metadata" "playback" "connect" "librespot" ) - -function replace_in_file() { - OS=`uname` - shopt -s nocasematch - case "$OS" in - darwin) - # for macOS - sed -i '' -e "$1" "$2" - ;; - *) - # for Linux and Windows - sed -i'' -e "$1" "$2" - ;; - esac -} - -function switchBranch { - if [ "$SKIP_MERGE" = 'false' ] ; then - # You are expected to have committed/stashed your changes before running this. - echo "Switching to master branch and merging development." - git checkout master - git pull - if [ "$DRY_RUN" = 'true' ] ; then - git merge --no-commit --no-ff dev - else - git merge dev - fi - fi -} - -function updateVersion { - for CRATE in "${crates[@]}" - do - if [ "$CRATE" = "librespot" ] - then - CRATE_DIR='' - else - CRATE_DIR=$CRATE - fi - crate_path="$WORKINGDIR/$CRATE_DIR/Cargo.toml" - crate_path=${crate_path//\/\///} - $(replace_in_file "s/^version =.*/version = \"$1\"/g" "$crate_path") - echo "Path is $crate_path" - if [ "$CRATE" = "librespot" ] - then - echo "Updating lockfile" - if [ "$DRY_RUN" = 'true' ] ; then - cargo update --dry-run - git add . && git commit --dry-run -a -m "Update Cargo.lock" - else - cargo update - git add . && git commit -a -m "Update Cargo.lock" - fi - fi - done -} - -function commitAndTag { - if [ "$DRY_RUN" = 'true' ] ; then - # Skip tagging on dry run. - git commit --dry-run -a -m "Update version numbers to $1" - else - git commit -a -m "Update version numbers to $1" - git tag "v$1" -a -m "Update to version $1" - fi -} - -function get_crate_name { - awk -v FS="name = " 'NF>1{print $2; exit}' Cargo.toml -} - -function publishCrates { - for CRATE in "${crates[@]}" - do - if [ "$CRATE" = "librespot" ] - then - CRATE='' - fi - - crate_path="$WORKINGDIR/$CRATE" - crate_path=${crate_path//\/\///} - cd $crate_path - # Also need to update Cargo.lock in root directory - crate_name=`echo $( awk -v FS="name = " 'NF>1{print $2; exit}' Cargo.toml )` - echo "Publishing $crate_name to crates.io" - if [ "$CRATE" == "protocol" ] - then - # Protocol crate needs --no-verify option due to build.rs modification. - if [ "$DRY_RUN" = 'true' ] ; then - cargo publish --no-verify --dry-run - else - cargo publish --no-verify - fi - else - if [ "$DRY_RUN" = 'true' ] ; then - cargo publish --dry-run - else - cargo publish - fi - fi - echo "Successfully published $crate_name to crates.io" - done -} - -function updateRepo { - cd $WORKINGDIR - if [ "$DRY_RUN" = 'true' ] ; then - echo "Pushing to master branch of repo. [DRY RUN]" - git push --dry-run origin master - echo "Pushing v$1 tag to master branch of repo. [DRY RUN]" - git push --dry-run origin v$1 - - # Cancels any merges in progress - git merge --abort - - git checkout dev - git merge --no-commit --no-ff master - - # Cancels above merge - git merge --abort - - git push --dry-run - else - echo "Pushing to master branch of repo." - git push origin master - echo "Pushing v$1 tag to master branch of repo." - git push origin v$1 - # Update the dev repo with latest version commit - git checkout dev - git merge master - git push - fi -} - -function rebaseDev { - git checkout dev - git merge master - git push -} - -function run { - switchBranch - updateVersion $1 - commitAndTag $1 - publishCrates - updateRepo $1 - rebaseDev - echo "Successfully published v$1 to crates.io and uploaded changes to repo." -} - -#Set Script Name variable -SCRIPT=`basename ${BASH_SOURCE[0]}` - -print_usage () { - local l_MSG=$1 - if [ ! -z "${l_MSG}" ]; then - echo "Usage Error: $l_MSG" - fi - echo "Usage: $SCRIPT " - echo " where specifies the version number in semver format, eg. 1.0.1" - echo "Recognized optional command line arguments" - echo "--dry-run -- Test the script before making live changes" - echo "--skip-merge -- Skip merging dev into master before publishing" - exit 1 -} - -### check number of command line arguments -NUMARGS=$# -if [ $NUMARGS -eq 0 ]; then - print_usage 'No command line arguments specified' -fi - -while test $# -gt 0; do - case "$1" in - -h|--help) - print_usage - exit 0 - ;; - --dry-run) - DRY_RUN='true' - shift - ;; - --skip-merge) - SKIP_MERGE='true' - shift - ;; - *) - break - ;; - esac -done - -# First argument is new version number. -run $1 From b0f8c5e8faed087f9cb60364b2da4ccd998ec329 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 24 Sep 2025 22:40:11 +0200 Subject: [PATCH 05/10] chore: change all variables into lower case --- .github/scripts/bump-versions.sh | 54 +++++++++++++------------- .github/scripts/get-excluded-crates.sh | 26 ++++++------- .github/workflows/prepare-release.yml | 2 +- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.github/scripts/bump-versions.sh b/.github/scripts/bump-versions.sh index 4fa1379a4..c8736c7a0 100755 --- a/.github/scripts/bump-versions.sh +++ b/.github/scripts/bump-versions.sh @@ -1,67 +1,67 @@ #!/usr/bin/env bash -# $FRAGMENT: see possible options https://github.com/christian-draeger/increment-semantic-version/tree/1.2.3?tab=readme-ov-file#version-fragment -if [ "$FRAGMENT" = "" ]; then - FRAGMENT=$1 +# $fragment: see possible options https://github.com/christian-draeger/increment-semantic-version/tree/1.2.3?tab=readme-ov-file#version-fragment +if [ "$fragment" = "" ]; then + fragment=$1 fi -CRATES="protocol oauth core discovery audio metadata playback connect" +allowed_crates="protocol oauth core discovery audio metadata playback connect" -if [ "$FRAGMENT" = "patch" ]; then - LAST_TAG=$(git describe --tags --abbrev=0) - AWK_CRATES=$(echo "$CRATES" | tr ' ' '|') - DIFF_CRATES=$(git diff $LAST_TAG... --stat --name-only \ +if [ "$fragment" = "patch" ]; then + last_tag=$(git describe --tags --abbrev=0) + awk_crates=$(echo "$allowed_crates" | tr ' ' '|') + diff_crates=$(git diff $last_tag... --stat --name-only \ | awk '/(rs|proto)$/{print}' \ - | awk "/($AWK_CRATES)/{print}" \ + | awk "/($awk_crates)/{print}" \ | cut -d '/' -f 1 \ | uniq \ | tr \\n '\ ' \ | xargs ) - echo "upgrading the following crates: [$DIFF_CRATES]" + echo "upgrading the following crates: [$diff_crates]" else - DIFF_CRATES=$CRATES + diff_crates=$allowed_crates echo "upgrading all crates for consistency" fi # append bin so that the version of the binary is also bumped -DIFF_CRATES="$DIFF_CRATES bin" +diff_crates="$diff_crates bin" # required by script as it's usually a github action export GITHUB_OUTPUT="version.txt" # https://github.com/christian-draeger/increment-semantic-version/tree/1.2.3 -INCREMENT_SEMVER=$(curl https://raw.githubusercontent.com/christian-draeger/increment-semantic-version/refs/tags/1.2.3/entrypoint.sh) +increment_semver=$(curl https://raw.githubusercontent.com/christian-draeger/increment-semantic-version/refs/tags/1.2.3/entrypoint.sh) -for CRATE in $DIFF_CRATES ; do - if [ "$CRATE" = "bin" ]; then - TOML="./Cargo.toml" +for crate in $diff_crates ; do + if [ "$crate" = "bin" ]; then + toml="./Cargo.toml" else - TOML="./$CRATE/Cargo.toml" + toml="./$crate/Cargo.toml" fi - FROM="$(cat $TOML | awk "/version/{print; exit}" | cut -d\" -f 2)" + from="$(cat $toml | awk "/version/{print; exit}" | cut -d\" -f 2)" # execute script inline, extract result and remove output file - echo "$INCREMENT_SEMVER" | bash /dev/stdin $FROM $FRAGMENT - TO=$(cat $GITHUB_OUTPUT | cut -d= -f 2) + echo "$increment_semver" | bash /dev/stdin $from $fragment + to=$(cat $GITHUB_OUTPUT | cut -d= -f 2) rm $GITHUB_OUTPUT - echo "upgrading [librespot-$CRATE] from [$FROM] to [$TO]" + echo "upgrading [librespot-$crate] from [$from] to [$to]" # replace version in associated crate toml - sed -i "0,/$FROM/{s/$FROM/$TO/}" $TOML + sed -i "0,/$from/{s/$from/$to/}" $toml - if [ "$CRATE" = "bin" ]; then + if [ "$crate" = "bin" ]; then continue fi # update workspace dependency in root toml - sed -i "/librespot-$CRATE/{s/$FROM/$TO/}" ./Cargo.toml + sed -i "/librespot-$crate/{s/$from/$to/}" ./Cargo.toml # update related dependencies in crate - for crate in $CRATES ; do - cat $TOML | grep librespot-$crate > /dev/null + for crate in $allowed_crates ; do + cat $toml | grep librespot-$crate > /dev/null if [ $? = 0 ]; then - sed -i "/librespot-$CRATE/{s/$FROM/$TO/}" $TOML + sed -i "/librespot-$crate/{s/$from/$to/}" $toml fi done done diff --git a/.github/scripts/get-excluded-crates.sh b/.github/scripts/get-excluded-crates.sh index 0a1fc4233..fc0e6401a 100755 --- a/.github/scripts/get-excluded-crates.sh +++ b/.github/scripts/get-excluded-crates.sh @@ -1,12 +1,12 @@ -CRATES="protocol oauth core discovery audio metadata playback connect" +allowed_crates="protocol oauth core discovery audio metadata playback connect" -CURRENT_TAG=$(git describe --abbrev=0) -LAST_TAG=$(git describe --abbrev=0 $CURRENT_TAG^) +current_tag=$(git describe --abbrev=0) +last_tag=$(git describe --abbrev=0 $current_tag^) -BIN_VERSION=$(cat ./Cargo.toml | awk "/version/{print; exit}" | cut -d\" -f 2) +bin_version=$(cat ./Cargo.toml | awk "/version/{print; exit}" | cut -d\" -f 2) -SIMPLE_VERSION_REGEX="^v?([0-9]+)\.([0-9]+)\.([0-9]+)$" -if [[ $LAST_TAG =~ $SIMPLE_VERSION_REGEX ]]; then +simple_version_regex="^v?([0-9]+)\.([0-9]+)\.([0-9]+)$" +if [[ $last_tag =~ $simple_version_regex ]]; then last_major="${BASH_REMATCH[1]}" last_minor="${BASH_REMATCH[2]}" last_patch="${BASH_REMATCH[3]}" @@ -15,7 +15,7 @@ else exit 1 fi -if [[ $BIN_VERSION =~ $SIMPLE_VERSION_REGEX ]]; then +if [[ $bin_version =~ $simple_version_regex ]]; then if [ "$last_major" != "${BASH_REMATCH[1]}" ] || [ "$last_minor" != "${BASH_REMATCH[2]}" ]; then echo "[]" exit 0 @@ -29,21 +29,21 @@ else fi # if we go through here, we build a patch version and only want to update the crates that have changed -AWK_CRATES=$(echo "$CRATES" | tr ' ' '|') -DIFF_CRATES=$(git diff $LAST_TAG... --stat --name-only \ +awk_crates=$(echo "$allowed_crates" | tr ' ' '|') +diff_crates=$(git diff $last_tag... --stat --name-only \ | awk '/(rs|proto)$/{print}' \ - | awk "/($AWK_CRATES)/{print}" \ + | awk "/($awk_crates)/{print}" \ | cut -d '/' -f 1 \ | uniq \ | tr '\n' ' ' \ | xargs \ | tr ' ' '|' ) -EXCLUDED_DIFF=$(echo $CRATES \ +excluded_diff=$(echo $allowed_crates \ | tr ' ' '\n' \ - | awk "!/($DIFF_CRATES)/{print}" \ + | awk "!/($diff_crates)/{print}" \ | tr '\n' ' ' \ | xargs \ | sed "s/ /\" }\, { \"crate\": \"/g") -echo "[ { \"crate\": \"$EXCLUDED_DIFF\" } ]" +echo "[ { \"crate\": \"$excluded_diff\" } ]" diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index a49d3188d..e7d070bc3 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -31,7 +31,7 @@ jobs: - name: Bump versions env: - FRAGMENT: ${{ github.event.inputs.versionBump }} + fragment: ${{ github.event.inputs.versionBump }} run: ./.github/scripts/bump-versions.sh - name: Update Cargo.lock From 6adb76546c04ede9f6f3abbbba5f8427df811d5e Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 24 Sep 2025 22:44:46 +0200 Subject: [PATCH 06/10] chore: adjust to review --- .github/scripts/bump-versions.sh | 4 ++-- .github/scripts/get-excluded-crates.sh | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/scripts/bump-versions.sh b/.github/scripts/bump-versions.sh index c8736c7a0..64f88de11 100755 --- a/.github/scripts/bump-versions.sh +++ b/.github/scripts/bump-versions.sh @@ -11,8 +11,8 @@ if [ "$fragment" = "patch" ]; then last_tag=$(git describe --tags --abbrev=0) awk_crates=$(echo "$allowed_crates" | tr ' ' '|') diff_crates=$(git diff $last_tag... --stat --name-only \ - | awk '/(rs|proto)$/{print}' \ - | awk "/($awk_crates)/{print}" \ + | awk '/\.(rs|proto)$/{print}' \ + | awk "/($awk_crates)\//{print}" \ | cut -d '/' -f 1 \ | uniq \ | tr \\n '\ ' \ diff --git a/.github/scripts/get-excluded-crates.sh b/.github/scripts/get-excluded-crates.sh index fc0e6401a..a4575634e 100755 --- a/.github/scripts/get-excluded-crates.sh +++ b/.github/scripts/get-excluded-crates.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + allowed_crates="protocol oauth core discovery audio metadata playback connect" current_tag=$(git describe --abbrev=0) @@ -31,8 +33,8 @@ fi # if we go through here, we build a patch version and only want to update the crates that have changed awk_crates=$(echo "$allowed_crates" | tr ' ' '|') diff_crates=$(git diff $last_tag... --stat --name-only \ - | awk '/(rs|proto)$/{print}' \ - | awk "/($awk_crates)/{print}" \ + | awk '/\.(rs|proto)$/{print}' \ + | awk "/($awk_crates)\//{print}" \ | cut -d '/' -f 1 \ | uniq \ | tr '\n' ' ' \ From 604550e62b554b9093075fb3591627622cdc5f08 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 24 Sep 2025 22:53:05 +0200 Subject: [PATCH 07/10] chore: extend instructions for github release --- .github/workflows/prepare-release.yml | 2 +- PUBLISHING.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index e7d070bc3..f677a1c4e 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -1,6 +1,6 @@ --- # test with -# act --job bump-crate-version --eventpath ./.github/example/prepare-release.event +# act --job prepare-release --eventpath ./.github/example/prepare-release.event name: prepare release on: workflow_dispatch: diff --git a/PUBLISHING.md b/PUBLISHING.md index 3c0bb95c2..d78f767cb 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -19,9 +19,9 @@ this can also be done manually if so desired. The workflow does: After everything is prepared for the new version. A [new release can be created](https://github.com/librespot-org/librespot/releases/new) from the ui. The tag will not be available as it isn't set by the prepare workflow, so a new tag needs to be created. -The tag should be named like `v` where `version` is the version of the binary. -> insert convention what the release title and release notes should be and what checkboxes to check etc. +The tag and name of the release should be named like `v` where `version` is the version of the binary to be +published. As release notes, copy the entries from the changelog for this release. The release should be created as draft, which will trigger the workflow that will publish the changed crates and binary. The workflow will: From 1dde323f3e3fbd118bc5e02638e95a6192b59b4e Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 24 Sep 2025 23:17:42 +0200 Subject: [PATCH 08/10] fix: update changes crates correctly --- .github/scripts/bump-versions.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/scripts/bump-versions.sh b/.github/scripts/bump-versions.sh index 64f88de11..a30cbd9e5 100755 --- a/.github/scripts/bump-versions.sh +++ b/.github/scripts/bump-versions.sh @@ -31,11 +31,11 @@ export GITHUB_OUTPUT="version.txt" # https://github.com/christian-draeger/increment-semantic-version/tree/1.2.3 increment_semver=$(curl https://raw.githubusercontent.com/christian-draeger/increment-semantic-version/refs/tags/1.2.3/entrypoint.sh) -for crate in $diff_crates ; do - if [ "$crate" = "bin" ]; then +for diff_crate in $diff_crates ; do + if [ "$diff_crate" = "bin" ]; then toml="./Cargo.toml" else - toml="./$crate/Cargo.toml" + toml="./$diff_crate/Cargo.toml" fi from="$(cat $toml | awk "/version/{print; exit}" | cut -d\" -f 2)" @@ -45,23 +45,23 @@ for crate in $diff_crates ; do to=$(cat $GITHUB_OUTPUT | cut -d= -f 2) rm $GITHUB_OUTPUT - echo "upgrading [librespot-$crate] from [$from] to [$to]" + echo "upgrading [librespot-$diff_crate] from [$from] to [$to]" - # replace version in associated crate toml + # replace version in associated diff_crate toml sed -i "0,/$from/{s/$from/$to/}" $toml - if [ "$crate" = "bin" ]; then + if [ "$diff_crate" = "bin" ]; then continue fi # update workspace dependency in root toml - sed -i "/librespot-$crate/{s/$from/$to/}" ./Cargo.toml + sed -i "/librespot-$diff_crate/{s/$from/$to/}" ./Cargo.toml - # update related dependencies in crate - for crate in $allowed_crates ; do - cat $toml | grep librespot-$crate > /dev/null + # update related dependencies in diff_crate + for allowed_crate in $allowed_crates ; do + cat ./$allowed_crate/Cargo.toml | grep librespot-$diff_crate > /dev/null if [ $? = 0 ]; then - sed -i "/librespot-$crate/{s/$from/$to/}" $toml + sed -i "/librespot-$diff_crate/{s/$from/$to/}" ./$allowed_crate/Cargo.toml fi done done From 921b75926e3a8067b3ba675ea741cc701c6116c6 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 24 Sep 2025 23:18:08 +0200 Subject: [PATCH 09/10] ci: publish workspace on release --- .github/scripts/get-excluded-crates.sh | 51 ------------------ .github/workflows/release.yml | 74 ++------------------------ 2 files changed, 4 insertions(+), 121 deletions(-) delete mode 100755 .github/scripts/get-excluded-crates.sh diff --git a/.github/scripts/get-excluded-crates.sh b/.github/scripts/get-excluded-crates.sh deleted file mode 100755 index a4575634e..000000000 --- a/.github/scripts/get-excluded-crates.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -allowed_crates="protocol oauth core discovery audio metadata playback connect" - -current_tag=$(git describe --abbrev=0) -last_tag=$(git describe --abbrev=0 $current_tag^) - -bin_version=$(cat ./Cargo.toml | awk "/version/{print; exit}" | cut -d\" -f 2) - -simple_version_regex="^v?([0-9]+)\.([0-9]+)\.([0-9]+)$" -if [[ $last_tag =~ $simple_version_regex ]]; then - last_major="${BASH_REMATCH[1]}" - last_minor="${BASH_REMATCH[2]}" - last_patch="${BASH_REMATCH[3]}" -else - echo "regex for tag didn't match" - exit 1 -fi - -if [[ $bin_version =~ $simple_version_regex ]]; then - if [ "$last_major" != "${BASH_REMATCH[1]}" ] || [ "$last_minor" != "${BASH_REMATCH[2]}" ]; then - echo "[]" - exit 0 - elif [ "$last_patch" == "${BASH_REMATCH[3]}" ]; then - echo "version didn't change" - exit 1 - fi -else - echo "regex for bin version didn't match" - exit 1 -fi - -# if we go through here, we build a patch version and only want to update the crates that have changed -awk_crates=$(echo "$allowed_crates" | tr ' ' '|') -diff_crates=$(git diff $last_tag... --stat --name-only \ - | awk '/\.(rs|proto)$/{print}' \ - | awk "/($awk_crates)\//{print}" \ - | cut -d '/' -f 1 \ - | uniq \ - | tr '\n' ' ' \ - | xargs \ - | tr ' ' '|' ) - -excluded_diff=$(echo $allowed_crates \ - | tr ' ' '\n' \ - | awk "!/($diff_crates)/{print}" \ - | tr '\n' ' ' \ - | xargs \ - | sed "s/ /\" }\, { \"crate\": \"/g") - -echo "[ { \"crate\": \"$excluded_diff\" } ]" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ec749799..e0ef70318 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,46 +6,11 @@ on: workflow_dispatch: jobs: - get-excluded-crates: - runs-on: ubuntu-latest - permissions: - contents: read - outputs: - excluded: ${{ steps.excluded-crates.outputs.EXCLUDE }} - steps: - - name: Checkout code - uses: actions/checkout@v5 - with: - fetch-tags: true - - - name: Get excluded crates - id: excluded-crates - run: | - EXCLUDE=$(./.github/scripts/get-excluded-crates.sh) - echo "excluding [$EXCLUDE]" - echo EXCLUDE=$EXCLUDE >> ${GITHUB_OUTPUT} - publish-crates: name: Publish crate librespot-${{ matrix.crate }} - needs: [ get-excluded-crates ] runs-on: ubuntu-latest permissions: contents: read - strategy: - max-parallel: 1 # for sequential execution because the order of publishing the crates is important - matrix: - # order is important - crate: - - protocol - - oauth - - core - - discovery - - audio - - metadata - - playback - - connect - # not all crates needs to be published all the time - exclude: ${{ fromJSON(needs.get-excluded-crates.outputs.excluded) }} steps: - name: Checkout code uses: actions/checkout@v5 @@ -60,42 +25,11 @@ jobs: if: ${{ contains('connect playback', matrix.crate ) }} # only install the dep when the crate requires it run: sudo apt-get update && sudo apt-get install -y libasound2-dev - - name: Verify librespot-${{ matrix.crate }} - run: cargo publish --package librespot-${{ matrix.crate }} --dry-run + - name: Verify librespot workspace + run: cargo publish --workspace --dry-run - - name: Publish librespot-${{ matrix.crate }} + - name: Publish librespot workspace if: ${{ !env.ACT }} env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - run: | - if [ "${{ matrix.crate }}" = "protocol" ]; then - cargo publish --package librespot-${{ matrix.crate }} --no-verify - else - cargo publish --package librespot-${{ matrix.crate }} - fi - - publish-binary: - name: publish librespot binary - needs: [ publish-crates ] - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - - - name: Cache Rust dependencies - uses: Swatinem/rust-cache@v2 - - - name: Install dependencies - run: sudo apt-get update && sudo apt-get install -y libasound2-dev - - - name: Verify librespot - run: cargo publish --dry-run --allow-dirty - - - name: Publish librespot - if: ${{ !env.ACT }} - run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: cargo publish --workspace --no-verify From f789004347fe15d104efda0c13e4efdf72568a64 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Wed, 24 Sep 2025 23:44:51 +0200 Subject: [PATCH 10/10] chore: fixup release workflow --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e0ef70318..79576514b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: jobs: publish-crates: - name: Publish crate librespot-${{ matrix.crate }} + name: Publish librespot runs-on: ubuntu-latest permissions: contents: read @@ -22,7 +22,6 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Install dependencies - if: ${{ contains('connect playback', matrix.crate ) }} # only install the dep when the crate requires it run: sudo apt-get update && sudo apt-get install -y libasound2-dev - name: Verify librespot workspace