mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-14 16:07:52 +00:00
Adds a nightly channel. Twice a day nightly.yml builds the newest main commit that passed CI and publishes it as a prerelease (OpenIDEA Nightly, ai.l0ng.openidea.nightly, own data and update manifest), or stops when nothing is newer than the last nightly. Platform builds move from release.yml into the reusable release-build.yml so both channels build the same way. Versions are one patch above main with a timestamp suffix; each build gets its own v…-nightly.… tag (remote development downloads the server by version) and the last 14 are kept; a rolling nightly release holds latest.json. No MSI or RPM for nightlies. Nightly builds skip the CNB mirror manifest, and their automatic update prompts (startup and periodic) appear at most once a day; a manual check always answers. Workflow permissions default to contents: read with write granted per job, Apple signing secrets reach only macOS builds, stable release.yml rejects nightly tags, tag pruning only matches -nightly. tags, and nightly runs share one concurrency group.
182 lines
7.5 KiB
YAML
182 lines
7.5 KiB
YAML
name: Release
|
||
on:
|
||
push:
|
||
tags: ["v*", "!v*-nightly.*"]
|
||
workflow_dispatch:
|
||
inputs:
|
||
tag:
|
||
description: "Tag to release (e.g. v0.1.0); must already exist"
|
||
required: true
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
concurrency:
|
||
group: release-${{ github.event.inputs.tag || github.ref_name }}
|
||
|
||
env:
|
||
CARGO_TERM_COLOR: always
|
||
CARGO_INCREMENTAL: 0
|
||
TAG: ${{ github.event.inputs.tag || github.ref_name }}
|
||
COMMUNITY_PLUGINS_INDEX: https://github.com/l0ng-ai/openidea-plugins/releases/download/index/index.json
|
||
|
||
jobs:
|
||
# Creates (or reuses) one draft release that every platform build uploads into.
|
||
create-release:
|
||
if: ${{ !contains(github.event.inputs.tag || github.ref_name, '-nightly.') }}
|
||
permissions:
|
||
contents: write
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
release_id: ${{ steps.release.outputs.id }}
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
with: { ref: "${{ env.TAG }}" }
|
||
- name: Tag matches app version
|
||
run: |
|
||
app="v$(jq -r .version src-tauri/tauri.conf.json)"
|
||
if [ "$app" != "$TAG" ]; then
|
||
echo "::error::tag $TAG does not match tauri.conf.json version $app"
|
||
exit 1
|
||
fi
|
||
# A shipped plugin API is frozen: its WIT must be the snapshot api_frozen.rs checks later
|
||
# versions against (plugins/README.md, "Evolving the plugin API").
|
||
- name: Plugin API snapshot matches wit/
|
||
run: |
|
||
api() { sed -n 's/^package openidea:plugin@\(.*\);$/\1/p' "$1/plugin.wit"; }
|
||
snapshot=sdk/rust/openidea-plugin/tests/api/released
|
||
if [ "$(api wit)" != "$(api "$snapshot")" ]; then
|
||
echo "::error::plugin API $(api wit) ships without a snapshot ($snapshot is $(api "$snapshot")): copy wit/*.wit to $snapshot/"
|
||
exit 1
|
||
fi
|
||
- id: release
|
||
uses: actions/github-script@v8
|
||
with:
|
||
script: |
|
||
const tag = process.env.TAG;
|
||
const { owner, repo } = context.repo;
|
||
const releases = await github.paginate(github.rest.repos.listReleases, { owner, repo });
|
||
const existing = releases.find((r) => r.tag_name === tag);
|
||
if (existing) {
|
||
if (!existing.draft) core.setFailed(`release ${tag} is already published`);
|
||
core.setOutput("id", existing.id);
|
||
return;
|
||
}
|
||
// Nightly builds are prereleases: the notes span stable release to stable release.
|
||
const previous = releases.find((r) => !r.draft && !r.prerelease);
|
||
const { data: notes } = await github.rest.repos.generateReleaseNotes({
|
||
owner, repo, tag_name: tag, previous_tag_name: previous?.tag_name,
|
||
});
|
||
const { data } = await github.rest.repos.createRelease({
|
||
owner, repo, tag_name: tag, name: `OpenIDEA ${tag}`,
|
||
draft: true, prerelease: tag.includes("-"), body: notes.body,
|
||
});
|
||
core.setOutput("id", data.id);
|
||
|
||
binaries:
|
||
permissions:
|
||
contents: write
|
||
needs: create-release
|
||
uses: ./.github/workflows/release-build.yml
|
||
with:
|
||
tag: ${{ github.event.inputs.tag || github.ref_name }}
|
||
release_id: ${{ needs.create-release.outputs.release_id }}
|
||
secrets: inherit
|
||
|
||
# The official plugins, signed, and the marketplace index released apps read
|
||
# (releases/latest/download/plugins-index.json). They are not in the
|
||
# installers: users install them from Settings › Plugins. Without the
|
||
# signing key (secret PLUGIN_SIGNING_KEY: the file `openidea-plugin keygen`
|
||
# writes) nothing is published and the release goes on. The index also lists
|
||
# the community plugins of the registry (COMMUNITY_PLUGINS_INDEX; refreshed
|
||
# between releases by plugins-index.yml), and the release carries the
|
||
# openidea-plugin tool for Linux x64, which that workflow and the registry's
|
||
# checks run.
|
||
plugins:
|
||
permissions:
|
||
contents: write
|
||
needs: create-release
|
||
name: Official plugins
|
||
runs-on: ubuntu-22.04
|
||
env:
|
||
SIGNING_KEY: ${{ secrets.PLUGIN_SIGNING_KEY }}
|
||
steps:
|
||
- id: key
|
||
run: |
|
||
if [ -z "$SIGNING_KEY" ]; then
|
||
echo "::warning::PLUGIN_SIGNING_KEY is not set: the official plugins are not published"
|
||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||
fi
|
||
- uses: actions/checkout@v5
|
||
if: steps.key.outputs.skip != 'true'
|
||
with: { ref: "${{ env.TAG }}" }
|
||
- uses: dtolnay/rust-toolchain@stable
|
||
if: steps.key.outputs.skip != 'true'
|
||
with: { targets: wasm32-wasip2 }
|
||
- uses: Swatinem/rust-cache@v2
|
||
if: steps.key.outputs.skip != 'true'
|
||
with: { key: release-plugins }
|
||
- uses: pnpm/action-setup@v5
|
||
if: steps.key.outputs.skip != 'true'
|
||
with: { version: 11 }
|
||
- uses: actions/setup-node@v5
|
||
if: steps.key.outputs.skip != 'true'
|
||
with: { node-version: 22 }
|
||
# Builds the web pages; fails when a checked-in component isn't built from these sources.
|
||
- name: Build
|
||
if: steps.key.outputs.skip != 'true'
|
||
run: |
|
||
plugins/build.sh --check
|
||
cargo build --release --locked -p ide-host --bin openidea-plugin
|
||
- name: Pack, index and upload
|
||
if: steps.key.outputs.skip != 'true'
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
run: |
|
||
set -euo pipefail
|
||
tool="$PWD/target/release/openidea-plugin"
|
||
key="$RUNNER_TEMP/openidea.key"
|
||
out="$RUNNER_TEMP/market"
|
||
(umask 077 && printf '%s' "$SIGNING_KEY" > "$key")
|
||
trap 'rm -f "$key"' EXIT
|
||
mkdir -p "$out"
|
||
for dir in plugins/official/*/; do
|
||
id="$(sed -n 's/^id *= *"\(.*\)".*/\1/p' "$dir/plugin.toml" | head -1)"
|
||
version="$(sed -n 's/^version *= *"\(.*\)".*/\1/p' "$dir/plugin.toml" | head -1)"
|
||
"$tool" pack "$dir" --key "$key" --publisher openidea --out "$out/$id-$version.oiplugin"
|
||
done
|
||
# The published index's revocations, earlier keys and community plugins carry over.
|
||
curl -fsSL "https://github.com/$GITHUB_REPOSITORY/releases/latest/download/plugins-index.json" \
|
||
-o "$out/plugins-index.json" || rm -f "$out/plugins-index.json"
|
||
# Downloads point at this release: older versions kept for older IDEs stay where they were published.
|
||
"$tool" index "$out" --publisher openidea --name OpenIDEA --key "$key" --out "$out/plugins-index.json" \
|
||
--download-base "https://github.com/$GITHUB_REPOSITORY/releases/download/$TAG"
|
||
"$tool" merge "$out/plugins-index.json" "$COMMUNITY_PLUGINS_INDEX" --keep openidea ||
|
||
echo "::warning::the community plugins were not refreshed"
|
||
gzip -9 -c "$tool" > "$out/openidea-plugin-linux-x86_64.gz"
|
||
gh release upload "$TAG" "$out"/*.oiplugin "$out/plugins-index.json" \
|
||
"$out/openidea-plugin-linux-x86_64.gz" --clobber
|
||
|
||
publish:
|
||
permissions:
|
||
contents: write
|
||
needs: [create-release, binaries, plugins]
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/github-script@v8
|
||
env:
|
||
RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
|
||
with:
|
||
script: |
|
||
await github.rest.repos.updateRelease({
|
||
...context.repo, release_id: Number(process.env.RELEASE_ID), draft: false,
|
||
});
|
||
|
||
# The China mirror the updater's CNB source reads; a failure here leaves the GitHub release as is.
|
||
cnb-mirror:
|
||
needs: publish
|
||
uses: ./.github/workflows/cnb-mirror.yml
|
||
with: { tag: "${{ github.event.inputs.tag || github.ref_name }}" }
|
||
secrets: inherit
|