Skip to content
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

Add infrastructure for release automation and clean up build workflow #87

Merged
merged 3 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 20 additions & 24 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,45 +1,41 @@
# Builds and publishes the documentation website to gh-pages branch
name: Build docs
name: Build documentation

on:
push:
branches: [ main ]
workflow_dispatch:
concurrency:
group: build
cancel-in-progress: true
permissions:
# Both required by actions/deploy-pages
pages: write
id-token: write

jobs:
build:
name: Build documentation
runs-on: windows-latest
steps:
- uses: actions/checkout@v4.1.1
- uses: actions/checkout@v4
name: Checkout
with:
submodules: recursive

- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2

- name: Restore NuGet Packages
run: msbuild -t:restore src\bonsai\Bonsai.sln

- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v4.0.0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 7.x
dotnet-version: 8.x

- name: Setup DocFX
run: dotnet tool restore

- name: Build Documentation
- name: Build documentation
run: dotnet docfx docfx.json

- name: Checkout gh-pages
uses: actions/checkout@v4.1.1
with:
ref: gh-pages
path: gh-pages
- name: Publish to github pages
uses: peaceiris/actions-gh-pages@v3.9.3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: _site
force_orphan: true

- name: Upload GitHub Pages Artifact
uses: actions/upload-pages-artifact@v3

- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v4
103 changes: 103 additions & 0 deletions .github/workflows/gha.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# GitHub Actions Utility Functions
# https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions
import os
import sys

errors_were_printed = False

def fail_if_errors():
if errors_were_printed:
print("Exiting due to previous errors.")
sys.exit(1)

def print_error(message):
global errors_were_printed
errors_were_printed = True
print(f"::error::{message}")

def print_warning(message):
print(f"::warning::{message}")

def print_notice(message):
print(f"::notice::{message}")

def print_debug(message):
print(f"::debug::{message}")

def github_file_command(command, message):
command = f"GITHUB_{command}"
command_file = os.getenv(command)

if command_file is None:
print_error(f"Missing required GitHub environment variable '{command}'")
sys.exit(1)

if not os.path.exists(command_file):
print_error(f"'{command}' points to non-existent file '{command_file}')")
sys.exit(1)

with open(command_file, 'a') as command_file_handle:
command_file_handle.write(message)
command_file_handle.write('\n')

def set_output(name, value):
if isinstance(value, bool):
value = "true" if value else "false"
github_file_command("OUTPUT", f"{name}<<GHA_PY_EOF\n{value}\nGHA_PY_EOF")

def set_environment_variable(name, value):
github_file_command("ENV", f"{name}={value}")

def add_path(path):
github_file_command("PATH", path)

if __name__ == "__main__":
args = sys.argv

def pop_arg():
global args
if len(args) == 0:
print_error("Bad command line, not enough arguments specified.")
sys.exit(1)
result = args[0]
args = args[1:]
return result

def done_parsing():
if len(args) > 0:
print_error("Bad command line, too many arguments specified.")
sys.exit(1)

pop_arg() # Skip script name
command = pop_arg()
if command == "print_error":
message = pop_arg()
done_parsing()
print_error(message)
elif command == "print_warning":
message = pop_arg()
done_parsing()
print_warning(message)
elif command == "print_notice":
message = pop_arg()
done_parsing()
print_notice(message)
elif command == "set_output":
name = pop_arg()
value = pop_arg()
done_parsing()
set_output(name, value)
elif command == "set_environment_variable":
name = pop_arg()
value = pop_arg()
done_parsing()
set_environment_variable(name, value)
elif command == "add_path":
path = pop_arg()
done_parsing()
add_path(path)
else:
print_error(f"Unknown command '{command}'")
sys.exit(1)

fail_if_errors()
72 changes: 72 additions & 0 deletions .github/workflows/update-bonsai-version-info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
import os
import re

import gha

TEMPLATE_PATH = ".github/workflows/version-info-template.md"
INSTALLATION_ARTICLE_PATH = "articles/installation.md"

project_url_base = "https://github.com/bonsai-rx/bonsai/"

#==================================================================================================
# Get inputs
#==================================================================================================
def get_environment_variable(name) -> str:
ret = os.getenv(name)

if ret is None or ret == '':
gha.print_error(f"Missing required parameter '{name}'")
return ''

return ret

workflow_dispatch_version = get_environment_variable('workflow_dispatch_version')

# Handle forks for testing purposes
if os.getenv('is_canonical_docs_repo') != 'true':
project_fork_url = get_environment_variable('project_fork_url')
project_url_base = project_fork_url.removesuffix('.git')
if project_url_base[-1] != '/':
project_url_base += '/'

gha.fail_if_errors()

#==================================================================================================
# Populate template
#==================================================================================================

version_info = ""
with open(TEMPLATE_PATH, 'r', encoding='utf-8') as f:
version_info = f.read()

version_info = version_info.replace("$VERSION$", workflow_dispatch_version)
version_info = version_info.replace("$PROJECT_URL_BASE$", project_url_base)

#==================================================================================================
# Update article
#==================================================================================================

article = ""
with open(INSTALLATION_ARTICLE_PATH, 'r', encoding='utf-8') as f:
article = f.read()

def replace_function(match):
return f"{match.group(1)}{version_info}{match.group(3)}"

(article, replacement_count) = re.subn(
r'(<!-- \[RELEASE_INFO\].+?-->\r?\n)(.+)(<!-- \[/RELEASE_INFO\] -->)',
replace_function,
article,
1,
re.DOTALL
)

if replacement_count != 1:
gha.print_error(f"Failed to find the RELEASE_INFO block within '{INSTALLATION_ARTICLE_PATH}'.")
gha.fail_if_errors()

with open(INSTALLATION_ARTICLE_PATH, 'w',encoding='utf-8') as f:
f.write(article)

print(f"Bonsai release info in '{INSTALLATION_ARTICLE_PATH}' updated to {workflow_dispatch_version}.")
93 changes: 93 additions & 0 deletions .github/workflows/version-bump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# This workflow bumps the submodule version used for a particular project
# In the case of Bonsai being updated, this also updates the installation page with the latest version info
name: Update documented project version
run-name: Update `${{github.event.inputs.project}}` to `${{github.event.inputs.version}}`
on:
workflow_dispatch:
inputs:
project:
description: "The name of the project to be updated (IE: a folder name within the src directory)"
required: true
version:
description: "The target version to update to (IE: a Git tag in the project)"
required: true
project-fork-url:
description: "Git URL of the project for testing in forks"
default: ""
concurrency:
group: version-bump
permissions:
# Required to trigger GitHub Pages deployment
actions: write
# Required to push changes
contents: write
jobs:
update:
name: Update ${{github.event.inputs.project}} to ${{github.event.inputs.version}}
runs-on: ubuntu-latest
env:
PROJECT: ${{github.event.inputs.project}}
VERSION: ${{github.event.inputs.version}}
steps:
# ----------------------------------------------------------------------- Checkout
- name: Checkout
uses: actions/checkout@v4

# ----------------------------------------------------------------------- Override the submodule URL
# This is to support testing release automation in forks, it is disabled for the canonical docs repo
- name: Override ${{github.event.inputs.project}}'s submodule URL
if: vars.IS_CANONICAL_DOCS_REPO != 'true' && github.event.inputs.project-fork-url != ''
run: git config --local --add "submodule.src/$PROJECT.url" "$FORK_URL"
env:
FORK_URL: ${{github.event.inputs.project-fork-url}}

# ----------------------------------------------------------------------- Update the submodule
- name: Clone ${{github.event.inputs.project}} submodule
run: git submodule update --init "src/$PROJECT/"
- name: Update ${{github.event.inputs.project}} submodule
working-directory: src/${{github.event.inputs.project}}/
run: git checkout "refs/tags/$VERSION"
- name: Stage ${{github.event.inputs.project}} submodule
run: git add "src/$PROJECT/"

# ----------------------------------------------------------------------- Update the installation page
- name: Setup Python 3.11
if: github.event.inputs.project == 'bonsai'
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Update Bonsai version info
if: github.event.inputs.project == 'bonsai'
run: |
python .github/workflows/update-bonsai-version-info.py
git add articles/installation.md
env:
workflow_dispatch_version: ${{github.event.inputs.version}}
is_canonical_docs_repo: ${{vars.IS_CANONICAL_DOCS_REPO}}
project_fork_url: ${{github.event.inputs.project-fork-url}}

# ----------------------------------------------------------------------- Commit changes
# Skip the rest of the job if there aren't any changes to commit
# (IE: the submodule was already the relevant version)
- name: Check if update was necessary
id: pre-commit-check
run: |
(git diff-index --cached --exit-code HEAD \
&& python .github/workflows/gha.py print_notice "Version bump was no-op, no changes to commit.") \
|| python .github/workflows/gha.py set_output continue true
- name: Commit changes
if: steps.pre-commit-check.outputs.continue == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit -m "Update \`$PROJECT\` to \`$VERSION\`"
- name: Push changes
if: steps.pre-commit-check.outputs.continue == 'true'
run: git push
# The above push will not actually trigger a deployment as actions performed using temporary GitHub Actions tokens
# do not trigger events in order to avoid unintentional recursion. As such we manually trigger deployment.
- name: Trigger GitHub Pages deployment
PathogenDavid marked this conversation as resolved.
Show resolved Hide resolved
if: steps.pre-commit-check.outputs.continue == 'true'
run: gh workflow run build.yml
env:
GH_TOKEN: ${{github.token}}
4 changes: 4 additions & 0 deletions .github/workflows/version-info-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The latest stable release is: **$VERSION$**

[<i class="fa fa-download"></i> Download Installer (.exe)]($PROJECT_URL_BASE$releases/download/$VERSION$/Bonsai-$VERSION$.exe){class="btn btn-success"}
[<i class="fa fa-download"></i> Download Portable (.zip)]($PROJECT_URL_BASE$releases/download/$VERSION$/Bonsai.zip){class="btn btn-warning"}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Bonsai Documentation

[![](https://img.shields.io/github/actions/workflow/status/bonsai-rx/docs/build.yml?branch=main&style=flat-square&label=Deployment%20status)](https://github.com/bonsai-rx/docs/actions/workflows/build.yml)

This repo contains the technical reference manual for the Bonsai visual programming language, in addition to articles and examples that document the collective knowledge of the Bonsai user community.

# Would you like to contribute to this repo?
Expand Down
6 changes: 4 additions & 2 deletions articles/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ title: "Installing Bonsai"

# Installing Bonsai

The Bonsai editor is currently designed to work with the .NET framework on Windows desktop operating systems, version 7 or later. The easiest way to get started with Bonsai is by downloading the latest installer.
The Bonsai editor is currently designed to work with the .NET Framework on Windows desktop operating systems, version 7 or later. The easiest way to get started with Bonsai is by downloading the latest installer.

The latest stable release is: **2.8.3 (2.8.3.4546)**
<!-- [RELEASE_INFO] The info below is generated automatically by .github/workflows/update-version.yml, don't modify it by hand! -->
The latest stable release is: **2.8.3**

[<i class="fa fa-download"></i> Download Installer (.exe)](https://github.com/bonsai-rx/bonsai/releases/download/2.8.3/Bonsai-2.8.3.exe){class="btn btn-success"}
[<i class="fa fa-download"></i> Download Portable (.zip)](https://github.com/bonsai-rx/bonsai/releases/download/2.8.3/Bonsai.zip){class="btn btn-warning"}
<!-- [/RELEASE_INFO] -->

The installer will make sure that .NET and any other required system dependencies for running Bonsai are correctly setup in your computer.