-
-
Notifications
You must be signed in to change notification settings - Fork 550
Add Sparkle update channels (stable/beta/nightly) with nightly pipeline #1078
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
9cae3de
14f684e
65abb9e
369e043
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,169 @@ | ||||||||||||||||||||
| name: Nightly Branch Builds | ||||||||||||||||||||
|
|
||||||||||||||||||||
| on: | ||||||||||||||||||||
| push: | ||||||||||||||||||||
| branches: | ||||||||||||||||||||
| - main | ||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can drop the main nightly (at least for now), as main only gets code changes that are released into stable |
||||||||||||||||||||
| - dev | ||||||||||||||||||||
| paths: | ||||||||||||||||||||
| - "boringNotch/**" | ||||||||||||||||||||
| - "BoringNotchXPCHelper/**" | ||||||||||||||||||||
| - "boringNotch.xcodeproj/**" | ||||||||||||||||||||
| - "Configuration/**" | ||||||||||||||||||||
| - "mediaremote-adapter/**" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| concurrency: | ||||||||||||||||||||
| group: nightly-${{ github.ref_name }} | ||||||||||||||||||||
| cancel-in-progress: true | ||||||||||||||||||||
|
|
||||||||||||||||||||
| permissions: | ||||||||||||||||||||
| contents: write | ||||||||||||||||||||
|
|
||||||||||||||||||||
| env: | ||||||||||||||||||||
| PROJECT_NAME: boringNotch | ||||||||||||||||||||
|
|
||||||||||||||||||||
| jobs: | ||||||||||||||||||||
| prepare: | ||||||||||||||||||||
| name: Prepare nightly metadata | ||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||
| outputs: | ||||||||||||||||||||
| branch_name: ${{ steps.meta.outputs.branch_name }} | ||||||||||||||||||||
| commit_sha: ${{ steps.meta.outputs.commit_sha }} | ||||||||||||||||||||
| short_sha: ${{ steps.meta.outputs.short_sha }} | ||||||||||||||||||||
| tag: ${{ steps.meta.outputs.tag }} | ||||||||||||||||||||
| appcast_file: ${{ steps.meta.outputs.appcast_file }} | ||||||||||||||||||||
| build_number: ${{ steps.meta.outputs.build_number }} | ||||||||||||||||||||
| asset_name: ${{ steps.meta.outputs.asset_name }} | ||||||||||||||||||||
| steps: | ||||||||||||||||||||
| - name: Compute metadata | ||||||||||||||||||||
| id: meta | ||||||||||||||||||||
| run: | | ||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||
| BRANCH_NAME="${GITHUB_REF_NAME}" | ||||||||||||||||||||
| COMMIT_SHA="${GITHUB_SHA}" | ||||||||||||||||||||
| SHORT_SHA="${COMMIT_SHA::7}" | ||||||||||||||||||||
| TAG="nightly-${BRANCH_NAME}-${SHORT_SHA}" | ||||||||||||||||||||
| APPCAST_FILE="appcast-${BRANCH_NAME}.xml" | ||||||||||||||||||||
| BUILD_NUMBER="$(date -u +%Y%m%d%H%M%S)$(printf '%06d%02d' "${GITHUB_RUN_NUMBER:-0}" "${GITHUB_RUN_ATTEMPT:-0}")" | ||||||||||||||||||||
| ASSET_NAME="boringNotch-${BRANCH_NAME}-${SHORT_SHA}.dmg" | ||||||||||||||||||||
| { | ||||||||||||||||||||
| echo "branch_name=$BRANCH_NAME" | ||||||||||||||||||||
| echo "commit_sha=$COMMIT_SHA" | ||||||||||||||||||||
| echo "short_sha=$SHORT_SHA" | ||||||||||||||||||||
| echo "tag=$TAG" | ||||||||||||||||||||
| echo "appcast_file=$APPCAST_FILE" | ||||||||||||||||||||
| echo "build_number=$BUILD_NUMBER" | ||||||||||||||||||||
| echo "asset_name=$ASSET_NAME" | ||||||||||||||||||||
| } >> "$GITHUB_OUTPUT" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| build: | ||||||||||||||||||||
| name: Build nightly DMG | ||||||||||||||||||||
| needs: [prepare] | ||||||||||||||||||||
| uses: ./.github/workflows/build_reusable.yml | ||||||||||||||||||||
| with: | ||||||||||||||||||||
| head_ref: ${{ needs.prepare.outputs.branch_name }} | ||||||||||||||||||||
| version: "" | ||||||||||||||||||||
| build_number: ${{ needs.prepare.outputs.build_number }} | ||||||||||||||||||||
| xcode_version: "16.4" | ||||||||||||||||||||
| code_sign_identity: "Apple Development" | ||||||||||||||||||||
| commit_version_changes: false | ||||||||||||||||||||
| secrets: | ||||||||||||||||||||
| BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} | ||||||||||||||||||||
| P12_PASSWORD: ${{ secrets.P12_PASSWORD }} | ||||||||||||||||||||
| KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| publish: | ||||||||||||||||||||
| name: Publish nightly channel | ||||||||||||||||||||
| needs: [prepare, build] | ||||||||||||||||||||
| runs-on: macos-latest | ||||||||||||||||||||
| permissions: | ||||||||||||||||||||
| contents: write | ||||||||||||||||||||
| env: | ||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||
| SPARKLE_PRIVATE_KEY: ${{ secrets.PRIVATE_SPARKLE_KEY }} | ||||||||||||||||||||
| BRANCH_NAME: ${{ needs.prepare.outputs.branch_name }} | ||||||||||||||||||||
| COMMIT_SHA: ${{ needs.prepare.outputs.commit_sha }} | ||||||||||||||||||||
| SHORT_SHA: ${{ needs.prepare.outputs.short_sha }} | ||||||||||||||||||||
| TAG: ${{ needs.prepare.outputs.tag }} | ||||||||||||||||||||
| APPCAST_FILE: ${{ needs.prepare.outputs.appcast_file }} | ||||||||||||||||||||
| ASSET_NAME: ${{ needs.prepare.outputs.asset_name }} | ||||||||||||||||||||
| COMMIT_MESSAGE: ${{ github.event.head_commit.message }} | ||||||||||||||||||||
| steps: | ||||||||||||||||||||
| - name: Checkout branch | ||||||||||||||||||||
| uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 | ||||||||||||||||||||
| with: | ||||||||||||||||||||
| ref: ${{ env.BRANCH_NAME }} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Download DMG artifact | ||||||||||||||||||||
| uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 | ||||||||||||||||||||
| with: | ||||||||||||||||||||
| name: ${{ env.PROJECT_NAME }}.dmg | ||||||||||||||||||||
| path: Release | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Rename DMG to immutable name | ||||||||||||||||||||
| run: | | ||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||
| mv "Release/${PROJECT_NAME}.dmg" "Release/${ASSET_NAME}" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Create embedded release notes | ||||||||||||||||||||
| run: | | ||||||||||||||||||||
| ESCAPED_COMMIT_MESSAGE="$(printf '%s' "$COMMIT_MESSAGE" | sed -e 's/&/\&/g' -e 's/</\</g' -e 's/>/\>/g')" | ||||||||||||||||||||
| cat > Release/boringNotch.html <<HTML | ||||||||||||||||||||
| <h2>Nightly ${BRANCH_NAME}</h2> | ||||||||||||||||||||
| <p>Commit: <code>${COMMIT_SHA}</code></p> | ||||||||||||||||||||
| <p>Message: ${ESCAPED_COMMIT_MESSAGE}</p> | ||||||||||||||||||||
| <p>Source: <a href="https://github.com/TheBoredTeam/boring.notch/commit/${COMMIT_SHA}">View commit</a></p> | ||||||||||||||||||||
| HTML | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Generate signed nightly appcast | ||||||||||||||||||||
| run: | | ||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||
| test -x Configuration/sparkle/generate_appcast || { | ||||||||||||||||||||
| echo "::error::Configuration/sparkle/generate_appcast missing or not executable"; exit 1; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| DOWNLOAD_PREFIX="https://github.com/TheBoredTeam/boring.notch/releases/download/${TAG}/" | ||||||||||||||||||||
| printf '%s' "$SPARKLE_PRIVATE_KEY" | ./Configuration/sparkle/generate_appcast \ | ||||||||||||||||||||
|
Comment on lines
+124
to
+125
|
||||||||||||||||||||
| DOWNLOAD_PREFIX="https://github.com/TheBoredTeam/boring.notch/releases/download/${TAG}/" | |
| printf '%s' "$SPARKLE_PRIVATE_KEY" | ./Configuration/sparkle/generate_appcast \ | |
| GEN_APPCAST="./Configuration/sparkle/generate_appcast" | |
| if [ ! -x "$GEN_APPCAST" ]; then | |
| echo "Error: Expected appcast generator '$GEN_APPCAST' to exist and be executable." >&2 | |
| exit 1 | |
| fi | |
| DOWNLOAD_PREFIX="https://github.com/TheBoredTeam/boring.notch/releases/download/${TAG}/" | |
| printf '%s' "$SPARKLE_PRIVATE_KEY" | "$GEN_APPCAST" \ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -92,6 +92,12 @@ Please submit all translations to [Crowdin](https://crowdin.com/project/boring-n | |
|
|
||
| 4. **Be patient**: Reviews take time. Maintainers will get to your PR as soon as they can. | ||
|
|
||
| ### Release Channels (Maintainers) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't think we need this here, its not really related to contributing guidelines |
||
|
|
||
| - **Stable/Beta** are produced by the release workflow. | ||
| - **Nightly (Main/Dev)** builds are produced on code pushes to `main` and `dev` branches. | ||
| - Nightly builds are not generated from the `pull_request` event itself. | ||
|
|
||
| <!-- ## Code Style Guidelines | ||
|
|
||
| - Follow the existing code style and conventions used in the project | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,19 @@ | |
| // | ||
|
|
||
| import SwiftUI | ||
| import Defaults | ||
| import Sparkle | ||
|
|
||
| final class UpdateChannelUpdaterDelegate: NSObject, SPUUpdaterDelegate { | ||
| @objc func feedURLString(for updater: SPUUpdater) -> String? { | ||
| Defaults[.updateChannel].feedURLString | ||
| } | ||
|
|
||
| @objc func allowedChannels(for updater: SPUUpdater) -> Set<String> { | ||
| Defaults[.updateChannel].allowedSparkleChannels | ||
| } | ||
| } | ||
|
|
||
| final class CheckForUpdatesViewModel: ObservableObject { | ||
| @Published var canCheckForUpdates = false | ||
|
|
||
|
|
@@ -37,6 +48,7 @@ struct CheckForUpdatesView: View { | |
| struct UpdaterSettingsView: View { | ||
| private let updater: SPUUpdater | ||
|
|
||
| @Default(.updateChannel) private var updateChannel | ||
| @State private var automaticallyChecksForUpdates: Bool | ||
| @State private var automaticallyDownloadsUpdates: Bool | ||
|
|
||
|
|
@@ -47,21 +59,36 @@ struct UpdaterSettingsView: View { | |
| } | ||
|
|
||
| var body: some View { | ||
| Section { | ||
| Section( | ||
| header: HStack { | ||
| Text("Software updates") | ||
| }, | ||
| footer: Text( | ||
| NSLocalizedString( | ||
| "Stable and Beta come from official releases. Main and Dev use nightly builds from those branches.", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure about making nightly builds available here. Especially without any testing, these nightly builds will often be completely broken, so I feel like a seprating this might make more sense, but I'm not sure yet |
||
| comment: "Software updates channel footer" | ||
| ) | ||
| ) | ||
| ) { | ||
| Picker( | ||
| NSLocalizedString("Update channel", comment: "Software updates channel picker label"), | ||
| selection: $updateChannel | ||
| ) { | ||
| ForEach(UpdateChannel.allCases) { channel in | ||
| Text(channel.title).tag(channel) | ||
| } | ||
| } | ||
|
|
||
| Toggle("Automatically check for updates", isOn: $automaticallyChecksForUpdates) | ||
| .onChange(of: automaticallyChecksForUpdates) { _, newValue in | ||
| updater.automaticallyChecksForUpdates = newValue | ||
| } | ||
|
|
||
| Toggle("Automatically download updates", isOn: $automaticallyDownloadsUpdates) | ||
| .disabled(!automaticallyChecksForUpdates) | ||
| .onChange(of: automaticallyDownloadsUpdates) { _, newValue in | ||
| updater.automaticallyDownloadsUpdates = newValue | ||
| } | ||
| } header: { | ||
| HStack { | ||
| Text("Software updates") | ||
| } | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think nightly builds should be on every push, this should be a job that runs once a day