Skip to content

Commit c1ed52c

Browse files
committed
feat(ci)!: rework workflows and build processes
All Python setups route through one local action, and checks are much more conditional. There is more to be done, but this is a significant improvement in processing time and redundancy. As well, nightly builds are made (though not made as GitHub releases.. yet).
1 parent 0d855cb commit c1ed52c

15 files changed

Lines changed: 543 additions & 363 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# SPDX-FileCopyrightText: (c) TagStudio Contributors
2+
# SPDX-License-Identifier: CC0-1.0
3+
---
4+
name: Setup Python
5+
description: Combination of Python setup actions
6+
7+
inputs:
8+
skip-setup:
9+
default: 'false'
10+
description: Whether to skip setup actions and only execute installs
11+
groups:
12+
description: Newline-separated list of dependency groups to install
13+
14+
runs:
15+
using: composite
16+
steps:
17+
- name: Setup Python install
18+
if: inputs.skip-setup != 'true'
19+
uses: actions/setup-python@v6
20+
with:
21+
python-version: '3.12'
22+
23+
- name: Setup uv install
24+
if: inputs.skip-setup != 'true'
25+
uses: astral-sh/setup-uv@v8.2.0
26+
27+
- name: Run pip install (Windows)
28+
if: runner.os == 'Windows'
29+
env:
30+
INPUT_GROUPS: ${{ inputs.groups }}
31+
UV_PYTHON_DOWNLOADS: never
32+
UV_SYSTEM_PYTHON: '1'
33+
shell: pwsh
34+
run: |
35+
if (![string]::IsNullOrEmpty(${env:INPUT_GROUPS})) {
36+
$groupArgs = -split ${env:INPUT_GROUPS} -replace '^', '--group='
37+
}
38+
39+
uv pip install . ${groupArgs}
40+
41+
- name: Run pip install (non-Windows)
42+
if: runner.os != 'Windows'
43+
env:
44+
INPUT_GROUPS: ${{ inputs.groups }}
45+
UV_PYTHON_DOWNLOADS: never
46+
UV_SYSTEM_PYTHON: '1'
47+
shell: bash
48+
run: |
49+
extra_args=()
50+
51+
if [ -n "${INPUT_GROUPS}" ]; then
52+
while IFS= read -r group; do
53+
if [ -n "${group}" ]; then
54+
extra_args+=("--group=${group}")
55+
fi
56+
done <<<"${INPUT_GROUPS}"
57+
fi
58+
59+
uv pip install . "${extra_args[@]}"

.github/workflows/build.yml

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# SPDX-FileCopyrightText: (c) TagStudio Contributors
2+
# SPDX-License-Identifier: CC0-1.0
3+
4+
# TODO: This will be invoked by a 'Release' workflow in the future.
5+
---
6+
name: Build
7+
8+
on:
9+
push:
10+
tags:
11+
- v*
12+
schedule:
13+
# From: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#schedule
14+
# To decrease the chance of delay, schedule your workflow to run at a different time of the hour.
15+
- cron: 42 3 * * *
16+
timezone: America/Los_Angeles
17+
workflow_dispatch:
18+
19+
concurrency:
20+
group: ${{ github.workflow }}-${{ github.ref }}
21+
cancel-in-progress: true
22+
23+
defaults:
24+
run:
25+
shell: sh
26+
27+
jobs:
28+
meta:
29+
name: Metadata
30+
runs-on: ubuntu-latest
31+
outputs:
32+
type: ${{ steps.meta.outputs.type }}
33+
version: ${{ steps.meta.outputs.version }}
34+
steps:
35+
- name: Set metadata
36+
id: meta
37+
run: |
38+
type=Nightly
39+
if [ "${GITHUB_REF_TYPE}" = tag ]; then
40+
case ${GITHUB_REF_NAME} in
41+
v*)
42+
type=Release
43+
case ${GITHUB_REF_NAME} in
44+
*-pr*) type=Pre-${type} ;;
45+
esac
46+
;;
47+
esac
48+
fi
49+
50+
if [ ${type} = Nightly ]; then
51+
version=dev+$(date --iso-8601 | tr -d -)
52+
else
53+
version=${GITHUB_REF_NAME}
54+
fi
55+
56+
cat <<EOF >>"${GITHUB_OUTPUT}"
57+
type=${type}
58+
version=${version}
59+
EOF
60+
61+
build:
62+
strategy:
63+
fail-fast: ${{ needs.meta.outputs.type != 'Nightly' }}
64+
matrix:
65+
include:
66+
- os: ubuntu-22.04
67+
os-label: Linux x86
68+
69+
- os: macos-15-intel
70+
os-label: macOS x86
71+
72+
- os: macos-15
73+
os-label: macOS ARM
74+
75+
- os: windows-2022
76+
os-label: Windows x86
77+
78+
name: Build${{ needs.meta.outputs.type && format(' {0}', needs.meta.outputs.type) }}${{ matrix.os-label && format(' ({0})', matrix.os-label) }}
79+
needs: meta
80+
runs-on: ${{ matrix.os }}
81+
env:
82+
BUILD_PREFIX: tagstudio_${{ needs.meta.outputs.version }}
83+
steps:
84+
- name: Prepare build (Windows)
85+
if: runner.os == 'Windows'
86+
shell: pwsh
87+
run: |
88+
$dir = "${env:RUNNER_TEMP}/upload"
89+
New-Item -Path ${dir} -ItemType Directory -Force
90+
91+
$os = ${env:RUNNER_OS}.ToLower()
92+
$arch = uname -m
93+
94+
$commonPath = "${dir}/${env:BUILD_PREFIX}_${os}_${arch}"
95+
Add-Content -Path ${env:GITHUB_ENV} -Value @"
96+
BUILD_ARTIFACT_DEFAULT=${commonPath}.zip
97+
BUILD_ARTIFACT_PORTABLE=${commonPath}_portable.zip
98+
"@ -Encoding utf8
99+
100+
- name: Prepare build (non-Windows)
101+
if: runner.os != 'Windows'
102+
run: |
103+
dir=${RUNNER_TEMP}/upload
104+
mkdir -p "${dir}"
105+
os=$(
106+
tr '[:upper:]' '[:lower:]' <<EOF
107+
${RUNNER_OS}
108+
EOF
109+
)
110+
arch=$(uname -m)
111+
112+
common_path=${dir}/${BUILD_PREFIX}_${os}_${arch}
113+
artifact_default=${common_path}.tar.gz
114+
if [ "${RUNNER_OS}" = macOS ]; then
115+
artifact_portable=
116+
else
117+
artifact_portable=${common_path}_portable.tar.gz
118+
fi
119+
cat <<EOF >>"${GITHUB_ENV}"
120+
BUILD_ARTIFACT_DEFAULT=${artifact_default}
121+
${artifact_portable:+BUILD_ARTIFACT_PORTABLE=${artifact_portable}}
122+
EOF
123+
124+
- name: Checkout repository
125+
uses: actions/checkout@v7
126+
127+
- name: Setup Python
128+
uses: ./.github/actions/setup-python
129+
with:
130+
groups: build
131+
132+
- parallel:
133+
- name: Run PyInstaller (Linux)
134+
if: runner.os == 'Linux'
135+
run: |
136+
pyinstaller --distpath dist/default --workpath build/default scripts/tagstudio.spec
137+
tar czf "${BUILD_ARTIFACT_DEFAULT}" -C dist/default/tagstudio .
138+
139+
- name: Run PyInstaller (Linux portable)
140+
if: runner.os == 'Linux'
141+
run: |
142+
pyinstaller --distpath dist/portable --workpath build/portable scripts/tagstudio.spec -- --portable
143+
tar czf "${BUILD_ARTIFACT_PORTABLE}" -C dist/portable tagstudio
144+
145+
- name: Run PyInstaller (macOS)
146+
if: runner.os == 'macOS'
147+
run: |
148+
scripts/tagstudio.spec
149+
tar czf "${BUILD_ARTIFACT_DEFAULT}" -C dist TagStudio.app
150+
151+
- name: Run PyInstaller (Windows)
152+
if: runner.os == 'Windows'
153+
shell: pwsh
154+
run: |
155+
PyInstaller --distpath dist/default --workpath build/default scripts/tagstudio.spec
156+
Compress-Archive -Path dist/default/TagStudio -DestinationPath ${env:BUILD_ARTIFACT_DEFAULT}
157+
158+
- name: Run PyInstaller (Windows portable)
159+
if: runner.os == 'Windows'
160+
shell: pwsh
161+
run: |
162+
PyInstaller --distpath dist/portable --workpath build/portable scripts/tagstudio.spec -- --portable
163+
Compress-Archive -Path dist/portable/TagStudio.exe -DestinationPath ${env:BUILD_ARTIFACT_PORTABLE}
164+
165+
- parallel:
166+
- name: Upload build artifact
167+
uses: actions/upload-artifact@v7
168+
with:
169+
path: ${{ env.BUILD_ARTIFACT_DEFAULT }}
170+
if-no-files-found: error
171+
# Short retention for 'Pre-Release' and 'Release' because they get uploaded to a GitHub release.
172+
retention-days: &upload-artifact-retention-days ${{ case(needs.meta.outputs.type == 'Nightly', '7', '1') }}
173+
archive: false
174+
175+
- name: Upload build artifact (portable)
176+
if: env.BUILD_ARTIFACT_PORTABLE != ''
177+
uses: actions/upload-artifact@v7
178+
with:
179+
path: ${{ env.BUILD_ARTIFACT_PORTABLE }}
180+
if-no-files-found: error
181+
retention-days: *upload-artifact-retention-days
182+
archive: false
183+
184+
upload:
185+
permissions:
186+
contents: write
187+
188+
name: Upload Builds to Release
189+
needs: [meta, build]
190+
if: needs.meta.outputs.type != 'Nightly'
191+
runs-on: ubuntu-latest
192+
steps:
193+
- name: Download build artifacts
194+
uses: actions/download-artifact@v8
195+
with:
196+
path: ${{ runner.temp }}/download
197+
merge-multiple: 'true'
198+
skip-decompress: 'true'
199+
200+
- name: Upload build artifacts to release
201+
uses: softprops/action-gh-release@v3
202+
with:
203+
files: ${{ runner.temp }}/download/*

.github/workflows/build_docs.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# SPDX-FileCopyrightText: (c) TagStudio Contributors
2+
# SPDX-License-Identifier: CC0-1.0
3+
4+
# TODO: In the future, docs will be built (but not published) for PRs.
5+
---
6+
name: Build Docs
7+
8+
on:
9+
push:
10+
branches:
11+
- main
12+
paths:
13+
- .github/actions/setup-python/action.yml
14+
- .github/workflows/build_docs.yml
15+
- docs/**
16+
- CHANGELOG.md
17+
- mkdocs.yml
18+
workflow_dispatch:
19+
20+
concurrency:
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: true
23+
24+
defaults:
25+
run:
26+
shell: sh
27+
28+
jobs:
29+
publish:
30+
concurrency:
31+
group: ${{ github.workflow }}
32+
cancel-in-progress: true
33+
permissions:
34+
contents: write
35+
36+
name: Publish Docs
37+
runs-on: ubuntu-latest
38+
steps:
39+
- name: Checkout repository
40+
uses: actions/checkout@v7
41+
42+
- name: Setup Python
43+
uses: ./.github/actions/setup-python
44+
with:
45+
groups: docs
46+
47+
- name: Use cache
48+
uses: actions/cache@v6
49+
with:
50+
key: mkdocs-material-${{ github.run_id }}
51+
path: .cache
52+
restore-keys: |
53+
mkdocs-material-
54+
- name: Run mkdocs
55+
env:
56+
DISABLE_MKDOCS_2_WARNING: 'true'
57+
run: mkdocs gh-deploy --force

0 commit comments

Comments
 (0)