`git checkout master` after `git fetch origin master` switches to the
LOCAL master -- the one actions/checkout left at this run's own SHA --
not the ref just fetched. A nightly build takes long enough that master
has usually moved by the time it finishes, so the manifest gets its new
entry prepended to a stale copy and the push is rejected:
! [rejected] master -> master (non-fast-forward)
Run 1045 failed this way, and the log is unambiguous about it: "Your
branch is behind 'origin/master' by 1 commit, and can be fast-forwarded"
appears one line before the commit that could not be pushed.
`checkout -B master origin/master` is the fix, and it is right rather
than merely convenient. This step appends one version entry to the
manifest as it stands on master, so the base it edits has to be master.
Editing the copy this build happened to start from and then forcing it
through would silently drop whatever landed in between.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
205 lines
8.4 KiB
YAML
205 lines
8.4 KiB
YAML
name: 'Nightly Build'
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
paths-ignore:
|
|
- '**/*.md'
|
|
- 'manifest.json'
|
|
- 'manifest-nightly.json'
|
|
|
|
jobs:
|
|
nightly-build:
|
|
runs-on: linux/amd64
|
|
container:
|
|
image: gitea.tourolle.paris/dtourolle/srfplay-builder:latest
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
path: build-${{ github.run_id }}
|
|
|
|
- name: Compute nightly version
|
|
id: version
|
|
run: |
|
|
# Date-based nightly version: 1.0.<YYYYMMDD>.<run_number>
|
|
# The run_number suffix keeps multiple builds on the same day
|
|
# monotonically increasing so Jellyfin always offers the newest.
|
|
DATE=$(date -u +"%Y%m%d")
|
|
VERSION="1.0.${DATE}.${{ github.run_number }}"
|
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
echo "Nightly version: ${VERSION}"
|
|
|
|
- name: Set build version
|
|
working-directory: build-${{ github.run_id }}
|
|
run: |
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
sed -i "s/^version:.*/version: \"${VERSION}\"/" build.yaml
|
|
cat build.yaml
|
|
|
|
- name: Restore dependencies
|
|
working-directory: build-${{ github.run_id }}
|
|
run: dotnet restore Jellyfin.Plugin.SRFPlay.sln
|
|
|
|
- name: Build solution
|
|
working-directory: build-${{ github.run_id }}
|
|
run: dotnet build Jellyfin.Plugin.SRFPlay.sln --configuration Release --no-restore --no-self-contained /m:1
|
|
|
|
- name: Run tests
|
|
working-directory: build-${{ github.run_id }}
|
|
run: dotnet test Jellyfin.Plugin.SRFPlay.sln --no-build --configuration Release --verbosity normal
|
|
|
|
- name: Build Jellyfin Plugin
|
|
id: jprm
|
|
working-directory: build-${{ github.run_id }}
|
|
run: |
|
|
mkdir -p artifacts
|
|
jprm --verbosity=debug plugin build .
|
|
ARTIFACT=$(find . -name "*.zip" -type f -print -quit | sed 's|^\./||')
|
|
ARTIFACT_NAME=$(basename "${ARTIFACT}")
|
|
echo "artifact=${ARTIFACT}" >> $GITHUB_OUTPUT
|
|
echo "artifact_name=${ARTIFACT_NAME}" >> $GITHUB_OUTPUT
|
|
echo "Found artifact: ${ARTIFACT}"
|
|
|
|
- name: Calculate checksum
|
|
id: checksum
|
|
working-directory: build-${{ github.run_id }}
|
|
run: |
|
|
CHECKSUM=$(md5sum "${{ steps.jprm.outputs.artifact }}" | awk '{print $1}')
|
|
echo "checksum=${CHECKSUM}" >> $GITHUB_OUTPUT
|
|
echo "Checksum: ${CHECKSUM}"
|
|
|
|
- name: Delete existing nightly release
|
|
working-directory: build-${{ github.run_id }}
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
REPO_OWNER="${{ github.repository_owner }}"
|
|
REPO_NAME="${{ github.event.repository.name }}"
|
|
GITEA_URL="${{ github.server_url }}"
|
|
TAG="latest"
|
|
|
|
EXISTING=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases/tags/${TAG}")
|
|
|
|
if [ "$EXISTING" = "200" ]; then
|
|
RELEASE_ID=$(curl -s \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases/tags/${TAG}" | jq -r '.id')
|
|
|
|
echo "Deleting existing nightly release (ID: ${RELEASE_ID})..."
|
|
curl -s -X DELETE \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases/${RELEASE_ID}"
|
|
fi
|
|
|
|
curl -s -X DELETE \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/tags/${TAG}" || true
|
|
|
|
- name: Create nightly release
|
|
working-directory: build-${{ github.run_id }}
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
REPO_OWNER="${{ github.repository_owner }}"
|
|
REPO_NAME="${{ github.event.repository.name }}"
|
|
GITEA_URL="${{ github.server_url }}"
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
|
|
|
|
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases" \
|
|
-d "$(jq -n --arg tag "latest" --arg name "Nightly Build ${VERSION}" --arg body "SRFPlay Jellyfin Plugin nightly build ${VERSION} from master (${SHORT_SHA})." '{tag_name: $tag, name: $name, body: $body, target_commitish: "master", draft: false, prerelease: true}')")
|
|
|
|
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
|
|
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
RELEASE_ID=$(echo "$BODY" | jq -r '.id')
|
|
echo "Created release with ID: ${RELEASE_ID}"
|
|
else
|
|
echo "Failed to create release. HTTP ${HTTP_CODE}"
|
|
echo "$BODY"
|
|
exit 1
|
|
fi
|
|
|
|
# Upload plugin artifact
|
|
echo "Uploading plugin artifact..."
|
|
curl -f -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/zip" \
|
|
--data-binary "@${{ steps.jprm.outputs.artifact }}" \
|
|
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases/${RELEASE_ID}/assets?name=${{ steps.jprm.outputs.artifact_name }}"
|
|
|
|
# Upload build.yaml
|
|
echo "Uploading build.yaml..."
|
|
curl -f -X POST \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/x-yaml" \
|
|
--data-binary "@build.yaml" \
|
|
"${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases/${RELEASE_ID}/assets?name=build.yaml"
|
|
|
|
echo "Nightly release updated successfully!"
|
|
|
|
- name: Update manifest-nightly.json
|
|
working-directory: build-${{ github.run_id }}
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
REPO_OWNER="${{ github.repository_owner }}"
|
|
REPO_NAME="${{ github.event.repository.name }}"
|
|
GITEA_URL="${{ github.server_url }}"
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
CHECKSUM="${{ steps.checksum.outputs.checksum }}"
|
|
ARTIFACT_NAME="${{ steps.jprm.outputs.artifact_name }}"
|
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
DOWNLOAD_URL="${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/releases/download/latest/${ARTIFACT_NAME}"
|
|
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
|
|
|
|
git config user.name "Gitea Actions"
|
|
git config user.email "actions@gitea.tourolle.paris"
|
|
git fetch origin master
|
|
# -B against origin/master, not a bare `checkout master`. The bare
|
|
# form switches to the LOCAL master that actions/checkout left at the
|
|
# run's own SHA, so if master moved while the build ran -- and this is
|
|
# a nightly, so it usually has -- the manifest is edited on a stale
|
|
# base and the push is rejected non-fast-forward. Run 1045 failed
|
|
# exactly this way, having already printed "Your branch is behind
|
|
# 'origin/master' by 1 commit" one line before committing anyway.
|
|
#
|
|
# Resetting is right rather than merely convenient: this step appends
|
|
# one entry to the manifest as it stands on master, so the base it
|
|
# edits must be master, not whatever this build started from.
|
|
git checkout -B master origin/master
|
|
|
|
NEW_VERSION=$(cat <<EOF
|
|
{
|
|
"version": "${VERSION}",
|
|
"changelog": "Nightly build ${VERSION} (${SHORT_SHA})",
|
|
"targetAbi": "10.9.0.0",
|
|
"sourceUrl": "${DOWNLOAD_URL}",
|
|
"checksum": "${CHECKSUM}",
|
|
"timestamp": "${TIMESTAMP}"
|
|
}
|
|
EOF
|
|
)
|
|
|
|
# Prepend the new build and keep only the most recent 5 nightlies.
|
|
jq --argjson newver "${NEW_VERSION}" \
|
|
'.[0].versions = ([$newver] + .[0].versions)[0:5]' \
|
|
manifest-nightly.json > manifest.tmp && mv manifest.tmp manifest-nightly.json
|
|
|
|
git add manifest-nightly.json
|
|
git commit -m "Nightly: ${VERSION} (${SHORT_SHA})" || echo "No changes to commit"
|
|
git push origin master
|
|
|
|
- name: Cleanup
|
|
if: always()
|
|
run: rm -rf build-${{ github.run_id }}
|