Skip to content

Build Installers

Build Installers #3135

name: Build Installers
on:
schedule:
- cron: "0 4 * * *"
workflow_dispatch:
inputs:
publish-release:
description: "Publish Release"
required: false
type: boolean
default: true
pre-release:
description: "Pre-release"
required: false
type: boolean
default: true
concurrency:
# make publishing release concurrent (but others trigger not)
group: building-releases-${{ inputs.publish-release && 'prerelease' || github.run_id }}
jobs:
configure:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.read-version.outputs.version_full }}
version_base: ${{ steps.read-version.outputs.version }}
tag_name: v${{ steps.read-version.outputs.version_full }}
version_commit: ${{ steps.version_commit.outputs.commit_long_sha }}
pushed: ${{ steps.version_commit.outputs.pushed }}
tag_pushed: ${{ steps.version_commit.outputs.tag_pushed }}
if: github.event_name != 'schedule' || (github.event_name == 'schedule' && github.repository == 'quarto-dev/quarto-cli')
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get previous version
id: read-version
run: |
source ./configuration
read_version=$(cat version.txt)
version=$(echo $read_version | grep -o '[[:digit:]]*\.[[:digit:]]*' | head -1)
if [ "$version" == "$QUARTO_VERSION" ]; then
## This should be the case only when we do a new patch release or for next pre-release to build.
build_number=$(($(echo $read_version | grep -o '[[:digit:]]*' | tail -1)+1))
else
## This should be the case only when we do a new major/minor release, for next pre-release to build.
version=$QUARTO_VERSION
build_number=0
news="news/changelog-${version}.md"
if [ ! -f "$news" ]; then
echo -e "All changes included in ${version}:\n\n" > $news
fi
fi
version_full=$version.$build_number
echo "version=$version" >> $GITHUB_OUTPUT
echo "version_full=$version_full">> $GITHUB_OUTPUT
echo "**Changelog since last release**: https://github.com/${GITHUB_REPOSITORY}/compare/v${read_version}...v${version_full}" > "release_note.md"
echo -e "\n\nFull ${version} changelog up to this version:\n" >> "release_note.md"
echo -e " * View: https://github.com/${GITHUB_REPOSITORY}/blob/v${version_full}/news/changelog-${version}.md\n" >> "release_note.md"
echo -e " * Download: https://github.com/${GITHUB_REPOSITORY}/releases/download/v${version_full}/changelog.md\n" >> "release_note.md"
# TODO: uncomment this again if new issue with RHEL build
# echo -e "" >> "release_note.md"
# echo -e "Due to an issue with upstream dependency, the RHEL build may not included in this release." >> "release_note.md"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: News
path: |
./news/changelog-${{steps.read-version.outputs.version}}.md
./release_note.md
- name: Update version.txt
run: |
echo ${{ steps.read-version.outputs.version_full }} > version.txt
- uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5
if: ${{ inputs.publish-release }}
id: version_commit
with:
add: '["version.txt", "news/changelog-${{steps.read-version.outputs.version}}.md"]'
tag: v${{ steps.read-version.outputs.version_full }}
message: "Update version.txt"
fetch: true
default_author: github_actions
make-source-tarball:
runs-on: ubuntu-latest
needs: [configure]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Make Tarball
run: |
tar --owner=root --group=root -zcvf quarto-${{needs.configure.outputs.version}}.tar.gz *
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Source
path: ./quarto-${{needs.configure.outputs.version}}.tar.gz
make-tarball:
runs-on: ubuntu-latest
needs: [configure]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Configure
run: |
./configure.sh
- name: Prepare Distribution
run: |
pushd package/src/
./quarto-bld prepare-dist --set-version ${{needs.configure.outputs.version}} --log-level info
popd
- name: Make Tarball
run: |
pushd package/
mv pkg-working quarto-${{needs.configure.outputs.version}}
tar --owner=root --group=root -cvf quarto-${{needs.configure.outputs.version}}-linux-amd64.tar quarto-${{needs.configure.outputs.version}}
gzip quarto-${{needs.configure.outputs.version}}-linux-amd64.tar
mv quarto-${{needs.configure.outputs.version}} pkg-working
popd
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Deb Zip
path: ./package/quarto-${{needs.configure.outputs.version}}-linux-amd64.tar.gz
make-arm64-tarball:
runs-on: ubuntu-latest
needs: [configure]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Configure
run: |
./configure.sh
- name: Prepare Distribution
run: |
pushd package/src/
./quarto-bld prepare-dist --set-version ${{needs.configure.outputs.version}} --arch aarch64 --log-level info
popd
- name: Make Tarball
run: |
pushd package/
mv pkg-working quarto-${{needs.configure.outputs.version}}
tar --owner=root --group=root -cvf quarto-${{needs.configure.outputs.version}}-linux-arm64.tar quarto-${{needs.configure.outputs.version}}
gzip quarto-${{needs.configure.outputs.version}}-linux-arm64.tar
mv quarto-${{needs.configure.outputs.version}} pkg-working
popd
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Deb Arm64 Zip
path: ./package/quarto-${{needs.configure.outputs.version}}-linux-arm64.tar.gz
make-tarball-rhel:
runs-on: ubuntu-latest
needs: [configure]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Configure
run: |
./configure.sh
- name: Prepare Distribution
run: |
pushd package/src/
./quarto-bld prepare-dist --set-version ${{needs.configure.outputs.version}} --log-level info
popd
- name: Move Custom Deno
run: |
source ./configuration
echo Placing custom Deno ${DENO:1}. See available versions at https://anaconda.org/conda-forge/deno/files
curl -L https://anaconda.org/conda-forge/deno/${DENO:1}/download/linux-64/deno-${DENO:1}-hcab8b69_0.conda --output deno.conda
unzip deno.conda
tar --use-compress-program=unzstd -xvf pkg-deno-${DENO:1}-hcab8b69_0.tar.zst
cp bin/deno package/pkg-working/bin/tools/x86_64/deno
- name: Make Tarball
run: |
pushd package/
mv pkg-working quarto-${{needs.configure.outputs.version}}
tar --owner=root --group=root -cvf quarto-${{needs.configure.outputs.version}}-linux-rhel7-amd64.tar quarto-${{needs.configure.outputs.version}}
gzip quarto-${{needs.configure.outputs.version}}-linux-rhel7-amd64.tar
mv quarto-${{needs.configure.outputs.version}} pkg-working
popd
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: RHEL Zip
path: ./package/quarto-${{needs.configure.outputs.version}}-linux-rhel7-amd64.tar.gz
make-installer-arm64-deb:
runs-on: ubuntu-latest
needs: [configure]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Configure
run: |
./configure.sh
- name: Prepare Distribution
run: |
pushd package/src/
./quarto-bld prepare-dist --set-version ${{needs.configure.outputs.version}} --arch aarch64 --log-level info
popd
- name: Make Installer
run: |
pushd package/src/
./quarto-bld make-installer-deb --set-version ${{needs.configure.outputs.version}} --arch aarch64 --log-level info
popd
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Deb Arm64 Installer
path: ./package/out/quarto-${{needs.configure.outputs.version}}-linux-arm64.deb
make-installer-deb:
runs-on: ubuntu-latest
needs: [configure]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Configure
run: |
./configure.sh
- name: Prepare Distribution
run: |
pushd package/src/
./quarto-bld prepare-dist --set-version ${{needs.configure.outputs.version}} --log-level info
popd
- name: Make Installer
run: |
pushd package/src/
./quarto-bld make-installer-deb --set-version ${{needs.configure.outputs.version}} --log-level info
popd
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Deb Installer
path: ./package/out/quarto-${{needs.configure.outputs.version}}-linux-amd64.deb
test-tarball-linux:
runs-on: ubuntu-latest
needs: [configure, make-tarball]
steps:
- uses: actions/download-artifact@v4
with:
name: Deb Zip
path: .
- run: |
tar -zxf quarto-${{needs.configure.outputs.version}}-linux-amd64.tar.gz
echo "$GITHUB_WORKSPACE/quarto-${{needs.configure.outputs.version}}/bin" >> $GITHUB_PATH
- run: |
tar -tzvf quarto-${{needs.configure.outputs.version}}-linux-amd64.tar.gz | head
ls -lR
echo $PATH
quarto check
quarto --paths
quarto --version
make-installer-win:
runs-on: windows-latest
needs: [configure]
steps:
- name: Configure Rust Tools
run: |
rustup.exe toolchain install 1.63.0 --component rustfmt --component clippy --no-self-update
rustup.exe default 1.63.0
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Configure
run: |
.\configure.cmd
- name: Prepare Distribution
run: |
pushd package\src\
.\quarto-bld.cmd prepare-dist --set-version ${{needs.configure.outputs.version}} --log-level info
popd
- name: Build Launcher
run: |
cargo build --release --all-features --manifest-path package/launcher/Cargo.toml
cp package/launcher/target/release/quarto.exe package/pkg-working/bin/quarto.exe
- name: Sign files before making ZIP and MSI installer
id: sign-files
uses: ./.github/workflows/actions/sign-files
with:
paths: |
./package/pkg-working/bin/quarto.exe
./package/pkg-working/bin/tools/x86_64/deno.exe
./package/pkg-working/bin/tools/x86_64/esbuild.exe
./package/pkg-working/bin/tools/x86_64/dart-sass/src/dart.exe
./package/pkg-working/bin/tools/x86_64/deno_dom/plugin.dll
./package/pkg-working/bin/tools/pandoc.exe
./package/pkg-working/bin/quarto.js
env:
# those environment variables are required to sign with signtool
SM_HOST: ${{ secrets.SM_HOST }}
SM_API_KEY: ${{ secrets.SM_API_KEY }}
SM_CLIENT_CERT_FILE_B64: ${{ secrets.SM_CLIENT_CERT_FILE_B64 }}
SM_CLIENT_CERT_PASSWORD: ${{ secrets.SM_CLIENT_CERT_PASSWORD }}
CERT_FINGERPRINT: ${{ secrets.SM_CLIENT_CERT_FINGERPRINT }}
- name: Make Installer
run: |
# Build installer
pushd package\src\
.\quarto-bld.cmd make-installer-win --set-version ${{needs.configure.outputs.version}} --log-level debug
popd
- name: Sign MSI installer
uses: ./.github/workflows/actions/sign-files
with:
paths: ./package/out/quarto-${{needs.configure.outputs.version}}-win.msi
signtools-extra-args: /d "Quarto CLI"
env:
# those environment variables are required to sign with signtool
SM_HOST: ${{ secrets.SM_HOST }}
SM_API_KEY: ${{ secrets.SM_API_KEY }}
SM_CLIENT_CERT_FILE_B64: ${{ secrets.SM_CLIENT_CERT_FILE_B64 }}
SM_CLIENT_CERT_PASSWORD: ${{ secrets.SM_CLIENT_CERT_PASSWORD }}
CERT_FINGERPRINT: ${{ secrets.SM_CLIENT_CERT_FINGERPRINT }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Windows Installer
path: ./package/out/quarto-${{needs.configure.outputs.version}}-win.msi
- name: Upload Zip
uses: actions/upload-artifact@v4
with:
name: Windows Zip
path: ./package/out/quarto-${{needs.configure.outputs.version}}-win.zip
test-zip-win:
runs-on: windows-latest
needs: [configure, make-installer-win]
steps:
- uses: actions/download-artifact@v4
with:
name: Windows Zip
path: .
- run: |
tar -xf quarto-${{needs.configure.outputs.version}}-win.zip
- run: Add-Content $env:GITHUB_PATH "$env:GITHUB_WORKSPACE\bin"
- run: |
quarto check
quarto --paths
quarto --version
make-installer-mac:
runs-on: macos-latest
needs: [configure]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.configure.outputs.version_commit }}
- name: Configure
run: |
./configure.sh
- uses: ./.github/workflows/actions/keychain
with:
certificate-value: ${{ secrets.APPLE_SIGN_P12 }}
certificate-password: ${{ secrets.APPLE_SIGN_PW }}
keychain: "build.keychain"
keychain-pw: ${{ secrets.APPLE_KEYCHAIN_PW }}
certificate-file: certificate.p12
- uses: ./.github/workflows/actions/keychain
with:
certificate-value: ${{ secrets.APPLE_INSTALLER_P12 }}
certificate-password: ${{ secrets.APPLE_INSTALLER_PW }}
keychain: "build.keychain"
keychain-pw: ${{ secrets.APPLE_KEYCHAIN_PW }}
certificate-file: installer.p12
- name: Prepare Distribution
run: |
security find-identity
security find-certificate -a
pushd package/src/
./quarto-bld prepare-dist --set-version ${{needs.configure.outputs.version}} --log-level info
popd
- name: Make Installer
run: |
pushd package/src/
./quarto-bld make-installer-mac --set-version ${{needs.configure.outputs.version}} --log-level info
popd
env:
QUARTO_APPLE_APP_DEV_ID: ${{ secrets.APPLE_SIGN_ID }}
QUARTO_APPLE_INST_DEV_ID: ${{ secrets.APPLE_INSTALLER_ID }}
QUARTO_APPLE_CONNECT_TEAMID: ${{ secrets.APPLE_CONNECT_TEAMID }}
QUARTO_APPLE_CONNECT_UN: ${{ secrets.APPLE_CONNECT_UN }}
QUARTO_APPLE_CONNECT_PW: ${{ secrets.APPLE_CONNECT_PW }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Mac Installer
path: ./package/out/quarto-${{needs.configure.outputs.version}}-macos.pkg
- name: Upload Zip
uses: actions/upload-artifact@v4
with:
name: Mac Zip
path: ./package/out/quarto-${{needs.configure.outputs.version}}-macos.tar.gz
- name: Cleanup Keychain
if: ${{ always() }}
run: |
security delete-keychain build.keychain
test-zip-mac:
runs-on: macos-latest
needs: [configure, make-installer-mac]
steps:
- uses: actions/download-artifact@v4
with:
name: Mac Zip
path: .
- run: |
tar -zxf quarto-${{needs.configure.outputs.version}}-macos.tar.gz
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
- run: tar -tzvf quarto-${{needs.configure.outputs.version}}-macos.tar.gz | head
- run: ls -lR
- run: echo $PATH
- run: |
quarto check
quarto --paths
quarto --version
publish-release:
if: ${{ inputs.publish-release }}
runs-on: ubuntu-latest
needs: [
configure,
make-installer-deb,
make-installer-arm64-deb,
make-installer-win,
make-installer-mac,
# optional in release to not be blocked by RHEL build depending on conda-forge deno dependency
# make-tarball-rhel,
make-arm64-tarball,
make-tarball,
make-source-tarball,
test-zip-win,
test-zip-mac,
test-tarball-linux,
]
steps:
- name: Download Artifacts
uses: actions/download-artifact@v4
- name: Rename news
run: |
ls -la ./News
mv ./News/news/changelog-${{needs.configure.outputs.version_base}}.md ./News/news/changelog.md
- name: Generate Checksums
id: generate_checksum
run: |
pushd Windows\ Installer
sha256sum quarto-${{needs.configure.outputs.version}}-win.msi >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
pushd Windows\ Zip
sha256sum quarto-${{needs.configure.outputs.version}}-win.zip >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
pushd Mac\ Zip
sha256sum quarto-${{needs.configure.outputs.version}}-macos.tar.gz >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
pushd Mac\ Installer
sha256sum quarto-${{needs.configure.outputs.version}}-macos.pkg >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
if [ -f "RHEL Zip/quarto-${{needs.configure.outputs.version}}-linux-rhel7-amd64.tar.gz" ]; then
pushd RHEL\ Zip
sha256sum quarto-${{needs.configure.outputs.version}}-linux-rhel7-amd64.tar.gz >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
fi
pushd Deb\ Zip
sha256sum quarto-${{needs.configure.outputs.version}}-linux-amd64.tar.gz >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
pushd Deb\ Arm64\ Zip
sha256sum quarto-${{needs.configure.outputs.version}}-linux-arm64.tar.gz >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
pushd Deb\ Installer
sha256sum quarto-${{needs.configure.outputs.version}}-linux-amd64.deb >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
pushd Deb\ Arm64\ Installer
sha256sum quarto-${{needs.configure.outputs.version}}-linux-arm64.deb >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
pushd Source
sha256sum quarto-${{needs.configure.outputs.version}}.tar.gz >> ../quarto-${{needs.configure.outputs.version}}-checksums.txt
popd
- name: Create Release
id: create_release
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{needs.configure.outputs.tag_name}}
target_commitish: ${{ needs.configure.outputs.version_commit }}
name: ${{needs.configure.outputs.tag_name}}
body_path: ./News/release_note.md
draft: false
prerelease: ${{ inputs.pre-release }}
fail_on_unmatched_files: false # rhel build may not be included
files: |
./Source/quarto-${{needs.configure.outputs.version}}.tar.gz
./Deb Zip/quarto-${{needs.configure.outputs.version}}-linux-amd64.tar.gz
./Deb Arm64 Zip/quarto-${{needs.configure.outputs.version}}-linux-arm64.tar.gz
./RHEL Zip/quarto-${{needs.configure.outputs.version}}-linux-rhel7-amd64.tar.gz
./Deb Installer/quarto-${{needs.configure.outputs.version}}-linux-amd64.deb
./Deb Arm64 Installer/quarto-${{needs.configure.outputs.version}}-linux-arm64.deb
./Windows Installer/quarto-${{needs.configure.outputs.version}}-win.msi
./Windows Zip/quarto-${{needs.configure.outputs.version}}-win.zip
./Mac Installer/quarto-${{needs.configure.outputs.version}}-macos.pkg
./Mac Zip/quarto-${{needs.configure.outputs.version}}-macos.tar.gz
./News/news/changelog.md
quarto-${{needs.configure.outputs.version}}-checksums.txt
cleanup-when-failure:
if: ${{ (failure() || cancelled()) && inputs.publish-release }}
needs: [
configure,
make-installer-deb,
make-installer-arm64-deb,
make-installer-win,
make-installer-mac,
# optional in release to not be blocked by RHEL build depending on conda-forge deno dependency
# make-tarball-rhel,
make-arm64-tarball,
make-tarball,
make-source-tarball,
test-zip-win,
test-zip-mac,
test-tarball-linux,
publish-release,
]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Revert commit of version.txt
if: ${{ needs.configure.outputs.pushed }}
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git pull origin $GITHUB_REF_NAME
git stash -u
git revert -n ${{ needs.configure.outputs.version_commit }}
git add .
git commit -m 'Revert version.txt update (${{ needs.configure.outputs.version_commit }})' -m 'Publishing release has failed.'
git push origin $GITHUB_REF_NAME
- name: Deleted created tag
if: ${{ needs.configure.outputs.tag_pushed }}
run: |
git push --delete origin ${{ needs.configure.outputs.tag_name }}
docker-push:
if: ${{ inputs.publish-release }}
runs-on: ubuntu-latest
needs: [configure, publish-release]
steps:
- name: Download Artifacts
uses: actions/download-artifact@v4
- uses: quarto-dev/quarto-cli/.github/actions/docker@main
with:
source: ./Deb Installer/quarto-${{needs.configure.outputs.version}}-linux-amd64.deb
version: ${{needs.configure.outputs.version}}
token: ${{ secrets.GITHUB_TOKEN }}
username: ${{ github.actor }}
org: ${{ github.repository_owner }}
name: quarto
daily: ${{ inputs.pre-release }}