Skip to content
Open
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
6 changes: 6 additions & 0 deletions .github/example/prepare-release.event
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"action": "workflow_dispatch",
"inputs": {
"versionBump": "minor"
}
}
69 changes: 69 additions & 0 deletions .github/scripts/bump-versions.sh
Original file line number Diff line number Diff line change
@@ -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

allowed_crates="protocol oauth core discovery audio metadata playback connect"

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}" \
| cut -d '/' -f 1 \
| uniq \
| tr \\n '\ ' \
| xargs )
echo "upgrading the following crates: [$diff_crates]"
else
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"

# 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)
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Downloading and executing arbitrary scripts from the internet without verification poses a security risk. Consider vendoring this script or using a verified GitHub Action instead.

Suggested change
increment_semver=$(curl https://raw.githubusercontent.com/christian-draeger/increment-semantic-version/refs/tags/1.2.3/entrypoint.sh)
increment_semver=$(cat .github/scripts/increment-semver-entrypoint.sh)

Copilot uses AI. Check for mistakes.


for diff_crate in $diff_crates ; do
if [ "$diff_crate" = "bin" ]; then
toml="./Cargo.toml"
else
toml="./$diff_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
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing downloaded script content through bash poses a security risk. The script content should be verified or the functionality should be implemented locally.

Copilot uses AI. Check for mistakes.

to=$(cat $GITHUB_OUTPUT | cut -d= -f 2)
rm $GITHUB_OUTPUT

echo "upgrading [librespot-$diff_crate] from [$from] to [$to]"

# replace version in associated diff_crate toml
sed -i "0,/$from/{s/$from/$to/}" $toml
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sed command may incorrectly replace version numbers that appear elsewhere in the file. It should be more specific to target only the version field, e.g., sed -i \"s/^version = \\\"$from\\\"/version = \\\"$to\\\"/\" $toml.

Suggested change
sed -i "0,/$from/{s/$from/$to/}" $toml
sed -i "s/^version = \"$from\"/version = \"$to\"/" $toml

Copilot uses AI. Check for mistakes.


if [ "$diff_crate" = "bin" ]; then
continue
fi

# update workspace dependency in root toml
sed -i "/librespot-$diff_crate/{s/$from/$to/}" ./Cargo.toml

# 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-$diff_crate/{s/$from/$to/}" ./$allowed_crate/Cargo.toml
fi
done
done

exit 0
2 changes: 0 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ name: build
- "LICENSE"
- "*.sh"
- "**/Dockerfile*"
- "publish.sh"
- "test.sh"
pull_request:
paths-ignore:
Expand All @@ -22,7 +21,6 @@ name: build
- "LICENSE"
- "*.sh"
- "**/Dockerfile*"
- "publish.sh"
- "test.sh"
schedule:
# Run CI every week
Expand Down
57 changes: 57 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
# test with
# act --job prepare-release --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
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter should be fetch-depth: 0 to fetch all history including tags. The fetch-tags parameter doesn't exist in actions/checkout.

Suggested change
fetch-tags: true
fetch-depth: 0

Copilot uses AI. Check for mistakes.


- 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/[email protected]
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 }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we check more generally for development environments besides ACT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And how would that look like? Or what different development environment do you have in mind?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah don't know how we can make that work with GitHub actions? Not an expert.

But if we would have something like:

if: ${{ env.PRODUCTION }}

then that could be more robust.

Can we set that environment variable somehow?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good point restricting it from the other side. I will take a look if there is something github provides.

Even tho I think this will break the intention of not running this step locally when using act, but I will report about that when I looked into it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I tried to find something similar that is supported by github out of the box, but I couldn't find anything. So only disabling it when using act seems good enough from my perspective.

with:
commit_message: 'Prepare for v${{ steps.get-version.outputs.VERSION }} release'
file_pattern: '*.md *.toml *.lock'
34 changes: 34 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: release.yml
on:
release:
types:
- created
workflow_dispatch:

jobs:
publish-crates:
name: Publish librespot
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 workspace
run: cargo publish --workspace --dry-run

- name: Publish librespot workspace
if: ${{ !env.ACT }}
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --workspace --no-verify
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,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
<https://github.com/librespot-org/librespot>

### Changed

Expand Down
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors.workspace = true
license.workspace = true
Expand Down Expand Up @@ -29,7 +29,6 @@ include = [
]

[workspace.package]
version = "0.7.1"
rust-version = "1.85"
authors = ["Librespot Org"]
license = "MIT"
Expand Down
55 changes: 27 additions & 28 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

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).
The tag and name of the release should be named like `v<version>` where `version` is the version of the binary to be
published. As release notes, copy the entries from the changelog for this release.

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.
2 changes: 1 addition & 1 deletion audio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-audio"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Paul Lietar <[email protected]>"]
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion connect/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-connect"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Paul Lietar <[email protected]>"]
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-core"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Paul Lietar <[email protected]>"]
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion discovery/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-discovery"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Paul Lietar <[email protected]>"]
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion metadata/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-metadata"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Paul Lietar <[email protected]>"]
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion oauth/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-oauth"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Nick Steel <[email protected]>"]
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion playback/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-playback"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Sasha Hilton <[email protected]>"]
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion protocol/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "librespot-protocol"
version.workspace = true
version = "0.7.1"
rust-version.workspace = true
authors = ["Paul Liétar <[email protected]>"]
license.workspace = true
Expand Down
Loading
Loading