Manual Release #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Manual Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version to release (e.g., 4.25.3)' | |
| required: true | |
| type: string | |
| target_commitish: | |
| description: 'Commit SHA or branch (leave empty for current HEAD)' | |
| required: false | |
| type: string | |
| release_notes: | |
| description: 'Release notes/changelog (leave empty to auto-generate from commits)' | |
| required: false | |
| type: string | |
| prerelease: | |
| description: 'Mark as prerelease' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| validate-version: | |
| name: Validate and Update Package Versions | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repo | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ inputs.target_commitish || github.ref }} | |
| fetch-depth: 0 | |
| token: ${{ secrets.UNRAID_BOT_GITHUB_ADMIN_TOKEN }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Check and Update Package Versions | |
| run: | | |
| EXPECTED_VERSION="${{ inputs.version }}" | |
| MISMATCHES_FOUND=false | |
| PACKAGE_JSONS=( | |
| "package.json" | |
| "api/package.json" | |
| "web/package.json" | |
| "unraid-ui/package.json" | |
| "plugin/package.json" | |
| "packages/unraid-shared/package.json" | |
| "packages/unraid-api-plugin-health/package.json" | |
| "packages/unraid-api-plugin-generator/package.json" | |
| "packages/unraid-api-plugin-connect/package.json" | |
| ) | |
| echo "Checking package.json versions against expected version: ${EXPECTED_VERSION}" | |
| for pkg in "${PACKAGE_JSONS[@]}"; do | |
| if [ -f "$pkg" ]; then | |
| CURRENT_VERSION=$(node -p "require('./$pkg').version") | |
| if [ "$CURRENT_VERSION" != "$EXPECTED_VERSION" ]; then | |
| echo "❌ Version mismatch in $pkg: $CURRENT_VERSION != $EXPECTED_VERSION" | |
| MISMATCHES_FOUND=true | |
| # Detect indentation by checking the first property line | |
| INDENT_SPACES=$(head -10 "$pkg" | grep '^ *"' | head -1 | sed 's/".*//g' | wc -c) | |
| INDENT_SPACES=$((INDENT_SPACES - 1)) | |
| jq --indent "$INDENT_SPACES" --arg version "$EXPECTED_VERSION" '.version = $version' "$pkg" > "$pkg.tmp" && mv "$pkg.tmp" "$pkg" | |
| echo "✓ Updated $pkg to version $EXPECTED_VERSION" | |
| else | |
| echo "✓ $pkg version matches: $CURRENT_VERSION" | |
| fi | |
| fi | |
| done | |
| if [ "$MISMATCHES_FOUND" = true ]; then | |
| echo "" | |
| echo "==========================================" | |
| echo "Version mismatches found!" | |
| echo "==========================================" | |
| echo "" | |
| BRANCH_OR_SHA="${{ inputs.target_commitish || github.ref }}" | |
| if git show-ref --verify --quiet "refs/heads/${BRANCH_OR_SHA}"; then | |
| echo "Creating commit with version updates and pushing to branch: ${BRANCH_OR_SHA}" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| BEFORE_SHA=$(git rev-parse HEAD) | |
| git add ${PACKAGE_JSONS[@]} | |
| git commit -m "chore: update package versions to ${{ inputs.version }}" | |
| git push origin "HEAD:${BRANCH_OR_SHA}" | |
| AFTER_SHA=$(git rev-parse HEAD) | |
| echo "" | |
| echo "==========================================" | |
| echo "WORKFLOW MUST BE RE-RUN" | |
| echo "==========================================" | |
| echo "" | |
| echo "✓ Version updates committed and pushed successfully" | |
| echo "" | |
| echo "Previous SHA: ${BEFORE_SHA}" | |
| echo "New SHA: ${AFTER_SHA}" | |
| echo "" | |
| echo "⚠️ CRITICAL: A new commit was created, but github.sha is immutable." | |
| echo "⚠️ github.sha = ${BEFORE_SHA} (original workflow trigger)" | |
| echo "⚠️ The release tag must point to ${AFTER_SHA} (with version updates)" | |
| echo "" | |
| echo "Re-run this workflow to create the release with the correct commit." | |
| echo "" | |
| exit 1 | |
| else | |
| echo "Target is a commit SHA, not a branch. Cannot push version updates." | |
| echo "Please update the package.json versions manually and re-run the workflow." | |
| exit 1 | |
| fi | |
| fi | |
| echo "" | |
| echo "✓ All package.json versions match the expected version: ${EXPECTED_VERSION}" | |
| build-artifacts: | |
| name: Build All Artifacts | |
| needs: | |
| - validate-version | |
| uses: ./.github/workflows/build-artifacts.yml | |
| with: | |
| ref: ${{ inputs.target_commitish || github.ref }} | |
| version_override: ${{ inputs.version }} | |
| secrets: | |
| VITE_ACCOUNT: ${{ secrets.VITE_ACCOUNT }} | |
| VITE_CONNECT: ${{ secrets.VITE_CONNECT }} | |
| VITE_UNRAID_NET: ${{ secrets.VITE_UNRAID_NET }} | |
| VITE_CALLBACK_KEY: ${{ secrets.VITE_CALLBACK_KEY }} | |
| UNRAID_BOT_GITHUB_ADMIN_TOKEN: ${{ secrets.UNRAID_BOT_GITHUB_ADMIN_TOKEN }} | |
| generate-release-notes: | |
| name: Generate Release Notes | |
| needs: | |
| - build-artifacts | |
| uses: ./.github/workflows/generate-release-notes.yml | |
| with: | |
| version: ${{ inputs.version }} | |
| target_commitish: ${{ inputs.target_commitish || github.ref }} | |
| release_notes: ${{ inputs.release_notes }} | |
| secrets: | |
| UNRAID_BOT_GITHUB_ADMIN_TOKEN: ${{ secrets.UNRAID_BOT_GITHUB_ADMIN_TOKEN }} | |
| create-release: | |
| name: Create GitHub Release (Draft) | |
| runs-on: ubuntu-latest | |
| needs: | |
| - generate-release-notes | |
| outputs: | |
| tag_name: ${{ steps.create_release.outputs.tag_name }} | |
| release_notes: ${{ needs.generate-release-notes.outputs.release_notes }} | |
| steps: | |
| - name: Checkout repo | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ inputs.target_commitish || github.ref }} | |
| fetch-depth: 0 | |
| - name: Create or Update Release as Draft | |
| id: create_release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG_NAME="v${{ inputs.version }}" | |
| TARGET="${{ inputs.target_commitish || github.sha }}" | |
| echo "tag_name=${TAG_NAME}" >> $GITHUB_OUTPUT | |
| if gh release view "${TAG_NAME}" > /dev/null 2>&1; then | |
| echo "Release ${TAG_NAME} already exists, updating as draft..." | |
| gh release edit "${TAG_NAME}" \ | |
| --draft \ | |
| --notes "${{ needs.generate-release-notes.outputs.release_notes }}" \ | |
| ${{ inputs.prerelease && '--prerelease' || '' }} | |
| else | |
| echo "Creating new draft release ${TAG_NAME}..." | |
| git tag "${TAG_NAME}" "${TARGET}" || true | |
| git push origin "${TAG_NAME}" || true | |
| gh release create "${TAG_NAME}" \ | |
| --draft \ | |
| --title "${{ inputs.version }}" \ | |
| --notes "${{ needs.generate-release-notes.outputs.release_notes }}" \ | |
| --target "${TARGET}" \ | |
| ${{ inputs.prerelease && '--prerelease' || '' }} | |
| fi | |
| build-plugin-production: | |
| name: Build and Deploy Production Plugin | |
| needs: | |
| - create-release | |
| - build-artifacts | |
| uses: ./.github/workflows/build-plugin.yml | |
| with: | |
| RELEASE_CREATED: 'true' | |
| RELEASE_TAG: ${{ needs.create-release.outputs.tag_name }} | |
| TAG: "" | |
| BUCKET_PATH: unraid-api | |
| BASE_URL: "https://stable.dl.unraid.net/unraid-api" | |
| BUILD_NUMBER: ${{ needs.build-artifacts.outputs.build_number }} | |
| ref: ${{ inputs.target_commitish || github.ref }} | |
| secrets: | |
| CF_ACCESS_KEY_ID: ${{ secrets.CF_ACCESS_KEY_ID }} | |
| CF_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }} | |
| CF_BUCKET_PREVIEW: ${{ secrets.CF_BUCKET_PREVIEW }} | |
| CF_ENDPOINT: ${{ secrets.CF_ENDPOINT }} | |
| UNRAID_BOT_GITHUB_ADMIN_TOKEN: ${{ secrets.UNRAID_BOT_GITHUB_ADMIN_TOKEN }} | |
| publish-release: | |
| name: Publish Release | |
| runs-on: ubuntu-latest | |
| needs: | |
| - create-release | |
| - build-plugin-production | |
| steps: | |
| - name: Publish Release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG_NAME="${{ needs.create-release.outputs.tag_name }}" | |
| echo "Publishing release ${TAG_NAME}..." | |
| gh release edit "${TAG_NAME}" --draft=false --repo ${{ github.repository }} | |