Skip to content

release

release #150

Workflow file for this run

name: release
on:
workflow_dispatch:
inputs:
force:
description: Force rebuild/publish even if the npm version already exists
required: false
default: "false"
schedule:
# Pacific daylight target times: 1am, 9am, 12pm, 3pm, 5pm, 7pm, 10pm.
- cron: "0 0,2,5,8,16,19,22 * * *"
jobs:
preflight:
runs-on: ubuntu-latest
outputs:
prod_outdated: ${{ steps.state.outputs.prod_outdated }}
beta_outdated: ${{ steps.state.outputs.beta_outdated }}
prod_version: ${{ steps.state.outputs.prod_version }}
beta_version: ${{ steps.state.outputs.beta_version }}
env:
NPM_PACKAGE_NAME: "codex-app-linux"
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- name: Check release state
id: state
run: |
node scripts/check-release-state.mjs \
--package-name "${NPM_PACKAGE_NAME}" \
--force "${{ github.event.inputs.force || 'false' }}" \
--json-output "dist/release-state.json"
echo "prod_outdated=$(jq -r '.channels.prod.outdated' dist/release-state.json)" >> "$GITHUB_OUTPUT"
echo "beta_outdated=$(jq -r '.channels.beta.outdated' dist/release-state.json)" >> "$GITHUB_OUTPUT"
echo "prod_version=$(jq -r '.channels.prod.packageVersion' dist/release-state.json)" >> "$GITHUB_OUTPUT"
echo "beta_version=$(jq -r '.channels.beta.packageVersion' dist/release-state.json)" >> "$GITHUB_OUTPUT"
publish-prod:
needs: preflight
if: github.event.inputs.force == 'true' || needs.preflight.outputs.prod_outdated == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
env:
NPM_CONFIG_PROVENANCE: "true"
NPM_PACKAGE_NAME: "codex-app-linux"
CODEX_RELEASE_REPO: "${{ github.repository }}"
AUR_PUBLISH_ENABLED: "${{ vars.AUR_PUBLISH_ENABLED || '' }}"
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
registry-url: https://registry.npmjs.org
- name: Install system deps
run: sudo apt-get update && sudo apt-get install -y p7zip-full jq libarchive-tools
- name: Install repo deps
run: npm ci
- name: Build channel
run: |
extra_args=""
if [ "${{ github.event.inputs.force || 'false' }}" = "true" ]; then
extra_args="--force"
fi
node scripts/release-channel.mjs \
--channel "prod" \
--json-output "dist/prod-release.json" \
$extra_args
- name: Read build metadata
id: meta
run: |
json="dist/prod-release.json"
echo "skipped=$(jq -r '.skipped // false' "$json")" >> "$GITHUB_OUTPUT"
echo "package_dir=$(jq -r '.packageDir // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "appimage=$(jq -r '.appImagePath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "tarball=$(jq -r '.unpackedTarballPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "icon=$(jq -r '.iconAssetPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "checksums=$(jq -r '.checksumsPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "pkgbuild=$(jq -r '.aurPackage.pkgbuildPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "srcinfo=$(jq -r '.aurPackage.srcinfoPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "install_script=$(jq -r '.aurPackage.installPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "aur_package_name=$(jq -r '.aurPackage.pkgname // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "aur_url=$(jq -r '.aurPackage.aurUrl // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "release_tag=$(jq -r '.releaseTag // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "package_version=$(jq -r '.packageVersion' "$json")" >> "$GITHUB_OUTPUT"
echo "prerelease=$(jq -r '.prerelease // false' "$json")" >> "$GITHUB_OUTPUT"
- name: Generate release notes
if: steps.meta.outputs.skipped != 'true'
run: |
node scripts/release-notes.mjs \
--channel "prod" \
--package-version "${{ steps.meta.outputs.package_version }}" \
--aur-package-name "${{ steps.meta.outputs.aur_package_name }}" \
> dist/prod-release-notes.md
- name: Upload workflow artifacts
if: steps.meta.outputs.skipped != 'true'
uses: actions/upload-artifact@v4
with:
name: prod-${{ steps.meta.outputs.package_version }}
path: |
${{ steps.meta.outputs.appimage }}
${{ steps.meta.outputs.tarball }}
${{ steps.meta.outputs.icon }}
${{ steps.meta.outputs.checksums }}
${{ steps.meta.outputs.pkgbuild }}
${{ steps.meta.outputs.srcinfo }}
${{ steps.meta.outputs.install_script }}
- name: Create or update GitHub release
if: steps.meta.outputs.skipped != 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if ! gh release view "${{ steps.meta.outputs.release_tag }}" >/dev/null 2>&1; then
prerelease_flag=""
if [ "${{ steps.meta.outputs.prerelease }}" = "true" ]; then
prerelease_flag="--prerelease"
fi
gh release create "${{ steps.meta.outputs.release_tag }}" \
--title "${{ steps.meta.outputs.release_tag }}" \
$prerelease_flag \
--notes-file dist/prod-release-notes.md
fi
gh release edit "${{ steps.meta.outputs.release_tag }}" \
--notes-file dist/prod-release-notes.md
gh release upload "${{ steps.meta.outputs.release_tag }}" \
"${{ steps.meta.outputs.appimage }}" \
"${{ steps.meta.outputs.tarball }}" \
"${{ steps.meta.outputs.icon }}" \
"${{ steps.meta.outputs.checksums }}" \
--clobber
- name: Publish npm package
if: steps.meta.outputs.skipped != 'true'
run: |
if npm view "codex-app-linux@${{ steps.meta.outputs.package_version }}" version >/dev/null 2>&1; then
echo "npm package version already exists; skipping publish"
exit 0
fi
npm publish "${{ steps.meta.outputs.package_dir }}" --provenance --access public --tag latest
- name: Publish AUR package
if: steps.meta.outputs.skipped != 'true'
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
run: |
if [ "${AUR_PUBLISH_ENABLED}" != "true" ]; then
echo "AUR publish not enabled; skipping"
exit 0
fi
if [ -z "${AUR_SSH_PRIVATE_KEY}" ]; then
echo "AUR SSH key missing; skipping"
exit 0
fi
install -dm700 ~/.ssh
printf '%s\n' "${AUR_SSH_PRIVATE_KEY}" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
touch ~/.ssh/known_hosts
for attempt in 1 2 3 4 5; do
if ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null; then
break
fi
if [ "$attempt" -eq 5 ]; then
echo "Failed to fetch AUR host key"
exit 1
fi
sleep 2
done
export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o IdentitiesOnly=yes"
git clone "ssh://aur@aur.archlinux.org/${{ steps.meta.outputs.aur_package_name }}.git" aur-prod
cp "${{ steps.meta.outputs.pkgbuild }}" aur-prod/PKGBUILD
cp "${{ steps.meta.outputs.srcinfo }}" aur-prod/.SRCINFO
cp "${{ steps.meta.outputs.install_script }}" "aur-prod/${{ steps.meta.outputs.aur_package_name }}.install"
git -C aur-prod config user.name "codex-app-linux bot"
git -C aur-prod config user.email "zero@composer.group"
git -C aur-prod add PKGBUILD .SRCINFO "${{ steps.meta.outputs.aur_package_name }}.install"
if git -C aur-prod diff --cached --quiet; then
echo "AUR package already current; skipping"
exit 0
fi
git -C aur-prod commit -m "Update to ${{ steps.meta.outputs.package_version }}"
git -C aur-prod push origin HEAD
publish-beta:
needs: preflight
if: github.event.inputs.force == 'true' || needs.preflight.outputs.beta_outdated == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
env:
NPM_CONFIG_PROVENANCE: "true"
NPM_PACKAGE_NAME: "codex-app-linux"
CODEX_RELEASE_REPO: "${{ github.repository }}"
AUR_PUBLISH_ENABLED: "${{ vars.AUR_PUBLISH_ENABLED || '' }}"
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
registry-url: https://registry.npmjs.org
- name: Install system deps
run: sudo apt-get update && sudo apt-get install -y p7zip-full jq libarchive-tools
- name: Install repo deps
run: npm ci
- name: Build channel
run: |
extra_args=""
if [ "${{ github.event.inputs.force || 'false' }}" = "true" ]; then
extra_args="--force"
fi
node scripts/release-channel.mjs \
--channel "beta" \
--json-output "dist/beta-release.json" \
$extra_args
- name: Read build metadata
id: meta
run: |
json="dist/beta-release.json"
echo "skipped=$(jq -r '.skipped // false' "$json")" >> "$GITHUB_OUTPUT"
echo "package_dir=$(jq -r '.packageDir // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "appimage=$(jq -r '.appImagePath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "tarball=$(jq -r '.unpackedTarballPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "icon=$(jq -r '.iconAssetPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "checksums=$(jq -r '.checksumsPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "pkgbuild=$(jq -r '.aurPackage.pkgbuildPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "srcinfo=$(jq -r '.aurPackage.srcinfoPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "install_script=$(jq -r '.aurPackage.installPath // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "aur_package_name=$(jq -r '.aurPackage.pkgname // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "aur_url=$(jq -r '.aurPackage.aurUrl // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "release_tag=$(jq -r '.releaseTag // ""' "$json")" >> "$GITHUB_OUTPUT"
echo "package_version=$(jq -r '.packageVersion' "$json")" >> "$GITHUB_OUTPUT"
echo "prerelease=$(jq -r '.prerelease // false' "$json")" >> "$GITHUB_OUTPUT"
- name: Generate release notes
if: steps.meta.outputs.skipped != 'true'
run: |
node scripts/release-notes.mjs \
--channel "beta" \
--package-version "${{ steps.meta.outputs.package_version }}" \
--aur-package-name "${{ steps.meta.outputs.aur_package_name }}" \
> dist/beta-release-notes.md
- name: Upload workflow artifacts
if: steps.meta.outputs.skipped != 'true'
uses: actions/upload-artifact@v4
with:
name: beta-${{ steps.meta.outputs.package_version }}
path: |
${{ steps.meta.outputs.appimage }}
${{ steps.meta.outputs.tarball }}
${{ steps.meta.outputs.icon }}
${{ steps.meta.outputs.checksums }}
${{ steps.meta.outputs.pkgbuild }}
${{ steps.meta.outputs.srcinfo }}
${{ steps.meta.outputs.install_script }}
- name: Create or update GitHub release
if: steps.meta.outputs.skipped != 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if ! gh release view "${{ steps.meta.outputs.release_tag }}" >/dev/null 2>&1; then
prerelease_flag=""
if [ "${{ steps.meta.outputs.prerelease }}" = "true" ]; then
prerelease_flag="--prerelease"
fi
gh release create "${{ steps.meta.outputs.release_tag }}" \
--title "${{ steps.meta.outputs.release_tag }}" \
$prerelease_flag \
--notes-file dist/beta-release-notes.md
fi
gh release edit "${{ steps.meta.outputs.release_tag }}" \
--notes-file dist/beta-release-notes.md
gh release upload "${{ steps.meta.outputs.release_tag }}" \
"${{ steps.meta.outputs.appimage }}" \
"${{ steps.meta.outputs.tarball }}" \
"${{ steps.meta.outputs.icon }}" \
"${{ steps.meta.outputs.checksums }}" \
--clobber
- name: Publish npm package
if: steps.meta.outputs.skipped != 'true'
run: |
if npm view "codex-app-linux@${{ steps.meta.outputs.package_version }}" version >/dev/null 2>&1; then
echo "npm package version already exists; skipping publish"
exit 0
fi
npm publish "${{ steps.meta.outputs.package_dir }}" --provenance --access public --tag beta
- name: Publish AUR package
if: steps.meta.outputs.skipped != 'true'
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
run: |
if [ "${AUR_PUBLISH_ENABLED}" != "true" ]; then
echo "AUR publish not enabled; skipping"
exit 0
fi
if [ -z "${AUR_SSH_PRIVATE_KEY}" ]; then
echo "AUR SSH key missing; skipping"
exit 0
fi
install -dm700 ~/.ssh
printf '%s\n' "${AUR_SSH_PRIVATE_KEY}" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
touch ~/.ssh/known_hosts
for attempt in 1 2 3 4 5; do
if ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null; then
break
fi
if [ "$attempt" -eq 5 ]; then
echo "Failed to fetch AUR host key"
exit 1
fi
sleep 2
done
export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o IdentitiesOnly=yes"
git clone "ssh://aur@aur.archlinux.org/${{ steps.meta.outputs.aur_package_name }}.git" aur-beta
cp "${{ steps.meta.outputs.pkgbuild }}" aur-beta/PKGBUILD
cp "${{ steps.meta.outputs.srcinfo }}" aur-beta/.SRCINFO
cp "${{ steps.meta.outputs.install_script }}" "aur-beta/${{ steps.meta.outputs.aur_package_name }}.install"
git -C aur-beta config user.name "codex-app-linux bot"
git -C aur-beta config user.email "zero@composer.group"
git -C aur-beta add PKGBUILD .SRCINFO "${{ steps.meta.outputs.aur_package_name }}.install"
if git -C aur-beta diff --cached --quiet; then
echo "AUR package already current; skipping"
exit 0
fi
git -C aur-beta commit -m "Update to ${{ steps.meta.outputs.package_version }}"
git -C aur-beta push origin HEAD