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
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ on:
push:
branches:
- master
# Skip when the release workflow already handles branch splitting
paths-ignore:
- 'CHANGELOG.md'
- '.github/workflows/release.yml'
jobs:
split-upm:
name: split upm branch
Expand Down
331 changes: 331 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
name: Release

on:
push:
branches:
- master
workflow_dispatch:
inputs:
version_bump:
description: 'Version bump type'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
release_notes:
description: 'Additional release notes (optional)'
required: false
type: string

permissions:
contents: write

jobs:
release:
name: Create Release
runs-on: ubuntu-latest
outputs:
new_version: ${{ steps.version.outputs.new_version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Get current version
id: current
run: |
CURRENT=$(grep -oP '"version":\s*"\K[^"]+' src/Proyecto26.RestClient/package.json)
echo "version=$CURRENT" >> $GITHUB_OUTPUT
echo "Current version: $CURRENT"

- name: Determine version bump from commits
id: bump
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "type=${{ inputs.version_bump }}" >> $GITHUB_OUTPUT
echo "Manual bump: ${{ inputs.version_bump }}"
else
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
RANGE="HEAD"
else
RANGE="${LAST_TAG}..HEAD"
fi
COMMITS=$(git log $RANGE --pretty=format:"%s" 2>/dev/null || echo "")
if echo "$COMMITS" | grep -qiE "^(feat|feature)(\(.+\))?!:|BREAKING CHANGE"; then
echo "type=major" >> $GITHUB_OUTPUT
elif echo "$COMMITS" | grep -qiE "^(feat|feature)(\(.+\))?:"; then
echo "type=minor" >> $GITHUB_OUTPUT
else
echo "type=patch" >> $GITHUB_OUTPUT
fi
fi

- name: Calculate new version
id: version
run: |
IFS='.' read -r MAJOR MINOR PATCH <<< "${{ steps.current.outputs.version }}"
case "${{ steps.bump.outputs.type }}" in
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
patch) PATCH=$((PATCH + 1)) ;;
esac
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "New version: $NEW_VERSION"

- name: Generate changelog entry
id: changelog
run: |
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then RANGE="HEAD"; else RANGE="${LAST_TAG}..HEAD"; fi

TODAY=$(date +%Y-%m-%d)
NEW_VERSION="${{ steps.version.outputs.new_version }}"
ADDED="" CHANGED="" FIXED="" REMOVED=""

while IFS= read -r line; do
HASH=$(echo "$line" | cut -d'|' -f1)
MSG=$(echo "$line" | cut -d'|' -f2-)
SHORT_HASH=$(echo "$HASH" | cut -c1-7)
PR_NUM=$(echo "$MSG" | grep -oP '\(#\K[0-9]+(?=\))' | head -1)

if [ -n "$PR_NUM" ]; then
ATTR="([#${PR_NUM}](https://github.com/proyecto26/RestClient/pull/${PR_NUM}))"
else
ATTR="([${SHORT_HASH}](https://github.com/proyecto26/RestClient/commit/${HASH}))"
fi

CLEAN_MSG=$(echo "$MSG" | sed -E 's/^(feat|fix|perf|refactor|chore|docs|style|test|build|ci)(\([^)]*\))?(!)?:\s*//')
CLEAN_MSG=$(echo "$CLEAN_MSG" | sed -E 's/\s*\(#[0-9]+\)\s*$//')

if echo "$MSG" | grep -qiE "^(feat|feature)(\(.+\))?:"; then
ADDED="${ADDED}- ${CLEAN_MSG} ${ATTR}.\n"
elif echo "$MSG" | grep -qiE "^fix(\(.+\))?:"; then
FIXED="${FIXED}- ${CLEAN_MSG} ${ATTR}.\n"
elif echo "$MSG" | grep -qiE "^(perf|refactor|chore|docs|style|build|ci)(\(.+\))?:"; then
CHANGED="${CHANGED}- ${CLEAN_MSG} ${ATTR}.\n"
elif echo "$MSG" | grep -qiE "^(revert)(\(.+\))?:"; then
REMOVED="${REMOVED}- ${CLEAN_MSG} ${ATTR}.\n"
else
CHANGED="${CHANGED}- ${CLEAN_MSG} ${ATTR}.\n"
fi
done < <(git log $RANGE --pretty=format:"%H|%s" --no-merges 2>/dev/null)

if [ -n "${{ inputs.release_notes }}" ]; then
ADDED="${ADDED}- ${{ inputs.release_notes }}\n"
fi

BODY=""
[ -n "$ADDED" ] && BODY="${BODY}### Added\n${ADDED}\n"
[ -n "$CHANGED" ] && BODY="${BODY}### Changed\n${CHANGED}\n"
[ -n "$FIXED" ] && BODY="${BODY}### Fixed\n${FIXED}\n"
[ -n "$REMOVED" ] && BODY="${BODY}### Removed\n${REMOVED}\n"
[ -z "$BODY" ] && BODY="### Changed\n- Release version ${NEW_VERSION}.\n"

echo -e "$BODY" > /tmp/release_body.md

# Update CHANGELOG.md
PREV_VERSION="${{ steps.current.outputs.version }}"
HEADER="## [${NEW_VERSION}] - ${TODAY}"
LINK="[${NEW_VERSION}]: https://github.com/proyecto26/RestClient/compare/v${PREV_VERSION}...v${NEW_VERSION}"
sed -i "/^## \[Unreleased\]/a\\\\n${HEADER}\\n" CHANGELOG.md
sed -i "/^## \[${NEW_VERSION}\]/r /tmp/release_body.md" CHANGELOG.md
sed -i "s|\[Unreleased\]: .*|[Unreleased]: https://github.com/proyecto26/RestClient/compare/v${NEW_VERSION}...HEAD|" CHANGELOG.md
sed -i "/^\[Unreleased\]:/a ${LINK}" CHANGELOG.md

- name: Update version in all files
run: |
VERSION="${{ steps.version.outputs.new_version }}"
sed -i 's/"version": "[^"]*"/"version": "'"$VERSION"'"/' src/Proyecto26.RestClient/package.json
sed -i 's/<PackageVersion>[^<]*</<PackageVersion>'"$VERSION"'</' src/Proyecto26.RestClient/Proyecto26.RestClient.csproj
sed -i 's/<version>[^<]*</<version>'"$VERSION"'</' src/Proyecto26.RestClient/Proyecto26.RestClient.nuspec
sed -i 's/AssemblyVersion ("[^"]*")/AssemblyVersion ("'"$VERSION"'")/' src/Proyecto26.RestClient/Properties/AssemblyInfo.cs

- name: Commit version bump
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add -A
git commit -m "chore(release): v${{ steps.version.outputs.new_version }}

- Updated package.json, .csproj, .nuspec, AssemblyInfo.cs
- Updated CHANGELOG.md"
git tag "v${{ steps.version.outputs.new_version }}"
git push origin master --follow-tags

# Build proper .unitypackage using the Unity package format
# Format: tar.gz of GUID directories, each containing asset, asset.meta, pathname
- name: Build .unitypackage
run: |
PKG_SRC="src/Proyecto26.RestClient"
STAGING="/tmp/unitypackage_staging"
UNITY_ROOT="Assets/Proyecto26.RestClient"
VERSION="${{ steps.version.outputs.new_version }}"
mkdir -p "$STAGING"

add_asset() {
local file="$1" meta="$2" unity_path="$3"
GUID=$(grep 'guid:' "$meta" | awk '{print $2}')
[ -z "$GUID" ] && return
mkdir -p "$STAGING/$GUID"
cp "$file" "$STAGING/$GUID/asset"
cp "$meta" "$STAGING/$GUID/asset.meta"
echo "$unity_path" > "$STAGING/$GUID/pathname"
}

add_folder_meta() {
local meta="$1" unity_path="$2"
GUID=$(grep 'guid:' "$meta" | awk '{print $2}')
[ -z "$GUID" ] && return
mkdir -p "$STAGING/$GUID"
cp "$meta" "$STAGING/$GUID/asset.meta"
echo "$unity_path" > "$STAGING/$GUID/pathname"
}

# Add source files (.cs, .asmdef, package.json) — exclude build system files
for f in $(find "$PKG_SRC" -type f \( -name "*.cs" -o -name "*.asmdef" -o -name "package.json" \) \
! -path "*/Properties/*" ! -path "*/bin/*" ! -path "*/obj/*"); do
META="${f}.meta"
if [ -f "$META" ]; then
REL_PATH="${f#$PKG_SRC/}"
add_asset "$f" "$META" "$UNITY_ROOT/$REL_PATH"
fi
done

# Add folder .meta files (e.g., Helpers.meta)
if [ -f "$PKG_SRC/Helpers.meta" ]; then
add_folder_meta "$PKG_SRC/Helpers.meta" "$UNITY_ROOT/Helpers"
fi

# Create the .unitypackage
cd "$STAGING"
ASSET_COUNT=$(ls -d */ 2>/dev/null | wc -l)
tar -czf "/tmp/Proyecto26.RestClient-${VERSION}.unitypackage" */
echo "Built .unitypackage with ${ASSET_COUNT} assets"

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version.outputs.new_version }}
name: Release ${{ steps.version.outputs.new_version }}
body_path: /tmp/release_body.md
draft: false
prerelease: false
files: |
/tmp/Proyecto26.RestClient-${{ steps.version.outputs.new_version }}.unitypackage

publish-nuget:
name: Publish to NuGet
needs: release
runs-on: ubuntu-latest
if: needs.release.outputs.new_version != ''
steps:
- uses: actions/checkout@v4
with:
ref: master

- name: Pull latest (includes version bump commit)
run: git pull origin master

# Use nuget CLI with .nuspec file (old-style .csproj is not compatible with dotnet pack)
- name: Install NuGet CLI
run: |
sudo apt-get update && sudo apt-get install -y nuget

- name: Build NuGet package
run: |
cd src/Proyecto26.RestClient
nuget pack Proyecto26.RestClient.nuspec -Version ${{ needs.release.outputs.new_version }} -OutputDirectory ../../artifacts

- name: Publish to NuGet
run: |
nuget push artifacts/*.nupkg \
-ApiKey ${{ secrets.NUGET_API_KEY }} \
-Source https://api.nuget.org/v3/index.json \
-SkipDuplicate
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}

split-branches:
name: Split UPM & NuGet branches
needs: release
runs-on: ubuntu-latest
if: needs.release.outputs.new_version != ''
steps:
- uses: actions/checkout@v4
with:
ref: master
fetch-depth: 0

- name: Pull latest
run: git pull origin master

- name: Split UPM branch
run: |
git branch -d upm &> /dev/null || echo "upm branch not found"
git mv "$PKG_ROOT" "src/$UPM_ROOT"
git mv "src/$UPM_ROOT" .
git mv demo/Assets demo/Samples~
git mv demo/Samples~ $UPM_ROOT
git mv doc Docs
git mv Docs $UPM_ROOT
git mv LICENSE $UPM_ROOT
git mv README.md $UPM_ROOT
git mv SECURITY.md $UPM_ROOT
git mv CHANGELOG.md $UPM_ROOT
git mv CONTRIBUTING.md $UPM_ROOT
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add "$UPM_ROOT"
git commit -m "create release folder"
git subtree split -P "$UPM_ROOT" -b upm
git checkout upm
# Remove non-Unity files that cause missing .meta warnings (fixes #219)
if [[ -d "Samples~/Packages" ]]; then
git rm -rf Samples~/Packages
git rm Samples~/Packages.meta --ignore-unmatch
git rm Samples~/packages.config
git rm Samples~/packages.config.meta --ignore-unmatch
fi
if [[ -d "Properties" ]]; then
git rm -rf Properties
git rm Properties.meta --ignore-unmatch
git rm Proyecto26.RestClient.csproj
git rm Proyecto26.RestClient.csproj.meta --ignore-unmatch
git rm Proyecto26.RestClient.nuspec
git rm Proyecto26.RestClient.nuspec.meta --ignore-unmatch
git rm packages.config
git rm packages.config.meta --ignore-unmatch
fi
git commit -am "fix: clean UPM branch (remove non-Unity files)"
git push -u origin upm --force
# Tag UPM branch for OpenUPM version detection
git tag "upm/${{ needs.release.outputs.new_version }}"
git push origin "upm/${{ needs.release.outputs.new_version }}"
env:
PKG_ROOT: src/Proyecto26.RestClient
UPM_ROOT: Release

- name: Split NuGet branch
run: |
git checkout master
git pull origin master
git branch -d nuget &> /dev/null || echo "nuget branch not found"
git mv LICENSE $NUGET_ROOT
git mv README.md $NUGET_ROOT
git mv SECURITY.md $NUGET_ROOT
git mv CHANGELOG.md $NUGET_ROOT
git mv CONTRIBUTING.md $NUGET_ROOT
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git subtree split -P "$NUGET_ROOT" -b nuget
git checkout nuget
git commit -am "fix: src => root" --allow-empty
git push -u origin nuget --force
env:
NUGET_ROOT: src
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.6.3] - 2025-11-22

### Fixed
- Fixed **ArgumentNullException** when calling `Abort()` or accessing properties on completed requests ([#103](https://github.com/proyecto26/RestClient/issues/103)).
- Enhanced disposal detection for UnityWebRequest objects to prevent crashes during cleanup scenarios.
- Added proper exception handling for all RequestHelper properties that access disposed UnityWebRequest instances.
- Improved thread safety for request cancellation in Unity's OnDestroy patterns.

## [2.6.2] - 2021-12-26

### Added
Expand Down
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,20 +338,18 @@ This project exists thanks to all the people who contribute. [[Contribute](CONTR

### Collaborators
<!-- COLLABORATORS-LIST:START - Do not remove or modify this section -->
[<img alt="jdnichollsc" src="https://avatars3.githubusercontent.com/u/2154886?v=3&s=117" width="117">](https://github.com/jdnichollsc) | [<img alt="diegoossa" src="https://avatars3.githubusercontent.com/u/3436237?v=3&s=117" width="117">](https://github.com/diegoossa) | [<img alt="nasdull" src="https://avatars3.githubusercontent.com/u/25492923?v=3&s=117" width="117">](https://github.com/nasdull) |
:---: | :---: | :---: |
[Juan Nicholls](mailto:jdnichollsc@hotmail.com) | [Diego Ossa](mailto:diegoossa@gmail.com) | [Nasdull](mailto:nasdull@hotmail.com) |
[<img alt="jdnichollsc" src="https://avatars3.githubusercontent.com/u/2154886?v=3&s=117" width="117">](https://github.com/jdnichollsc) | [<img alt="diegoossa" src="https://avatars3.githubusercontent.com/u/3436237?v=3&s=117" width="117">](https://github.com/diegoossa) | [<img alt="nasdull" src="https://avatars3.githubusercontent.com/u/25492923?v=3&s=117" width="117">](https://github.com/nasdull) | [<img alt="nasdull" src="https://avatars.githubusercontent.com/u/29339330?v=4" width="117">](https://github.com/maifeeulasad) |
:---: | :---: | :---: | :---: |
[Juan Nicholls](mailto:jdnichollsc@hotmail.com) | [Diego Ossa](mailto:diegoossa@gmail.com) | [Nasdull](mailto:nasdull@hotmail.com) | [Maifee Ul Asad](mailto:maifeeulasad@gmail.com) |
<!-- COLLABORATORS-LIST:END -->

## Supporting 🍻
I believe in Unicorns 🦄
Support [me](http://www.paypal.me/jdnichollsc/2), if you do too.

Donate **Ethereum**, **ADA**, **BNB**, **SHIBA**, **USDT**, **DOGE**:
Donate **Ethereum**, **ADA**, **BNB**, **SHIBA**, **USDT/USDC**, **DOGE**, etc:

![Wallet address](https://user-images.githubusercontent.com/2154886/123501719-84bf1900-d60c-11eb-882c-98a499cea323.png)

> Wallet address: 0x3F9fA8021B43ACe578C2352861Cf335449F33427
> Wallet address: jdnichollsc.eth

Please let us know your contributions! 🙏

Expand All @@ -364,6 +362,12 @@ The maintainers of RestClient for Unity and thousands of other packages are work
## Security contact information 🚨
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.

## Who is using RestClient ⚔️
We are battle tested. There is a list of our usage in production:
- mainware. Ref: https://github.com/proyecto26/RestClient/issues/138#issuecomment-725552712
- virsabi. Ref: https://github.com/proyecto26/RestClient/issues/138#issuecomment-863222899
- type3studio. Ref: https://github.com/proyecto26/RestClient/issues/138#issuecomment-1415945883

## License ⚖️
This repository is available under the [MIT License](https://github.com/proyecto26/RestClient/blob/develop/LICENSE).

Expand Down
Loading
Loading