Skip to content

Build

Build #482

Workflow file for this run

name: Build
on:
pull_request:
paths:
- .github/workflows/build.yml
- service/**
push:
branches:
- main
tags-ignore:
- "**"
paths:
- .github/workflows/build.yml
- service/**
workflow_dispatch:
inputs:
sign:
description: Sign binaries
type: choice
options:
- 'no'
- test
- production
default: test
cldr-version:
description: CLDR Version
type: string
required: false
iconv-version:
description: Iconv Version
type: string
required: false
curl-version:
description: Curl Version
type: string
required: false
json-c-version:
description: JSON-C Version
type: string
required: false
gettext-version:
description: Gettext Version
type: string
required: false
publish-release:
description: Publish release after build
type: boolean
required: false
permissions:
contents: write
jobs:
test-bash-scripts:
name: Test bash scripts
runs-on: ubuntu-latest
container:
image: mvdan/shfmt:v3.12.0-alpine
options: --entrypoint /bin/sh
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Check scripts
run: |
files="$(shfmt --find .)"
if [ $? -ne 0 ] || [ -z "$files" ]; then
echo 'Failed to list shell scripts'
exit 1
fi
rc=0
for file in $files; do
printf '# %s... ' "$file"
if shfmt --diff --simplify --indent 4 --case-indent --func-next-line -- "$file"; then
echo 'ok.'
else
rc=1
printf '\n\n'
fi
done
exit $rc
test-pwsh-scripts:
name: Test PowerShell scripts
runs-on: windows-latest
env:
PSScriptAnalyzerVersion: 1.24.0
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Create directory structure
run: |
New-Item -ItemType Directory -Force -ErrorAction Stop -Path @(
'downloads'
'tmp'
) | Out-Null
-
name: Restore cache
id: restore-cache
uses: actions/cache/restore@v5
with:
key: test-pwsh-scripts
path: downloads
-
name: Download PSScriptAnalyzer module
run: >
./service/download-archive.ps1
-Url "https://www.powershellgallery.com/api/v2/package/PSScriptAnalyzer/${env:PSScriptAnalyzerVersion}"
-LocalFilePath "downloads\psscriptanalyzer.${env:PSScriptAnalyzerVersion}.nupkg"
-
name: Extract PSScriptAnalyzer
working-directory: tmp
run: Expand-Archive -Path "..\downloads\psscriptanalyzer.${env:PSScriptAnalyzerVersion}.nupkg" -DestinationPath .\PSScriptAnalyzer
-
name: Import PSScriptAnalyzer module
working-directory: tmp
run: Import-Module -Name .\PSScriptAnalyzer\ -Force
-
name: Check scripts
run: |
$rc = 0
$files = Get-ChildItem -Path . -Recurse -File -Filter *.ps1
foreach ($file in $files) {
Write-Host -Object "# $($file.Name)... " -NoNewline
$records = Invoke-ScriptAnalyzer -Path $file -ExcludeRule PSAvoidUsingWriteHost,PSUseShouldProcessForStateChangingFunctions,PSUseSingularNouns
if (-not($records)) {
Write-Host -Object 'ok.'
} else {
$rc = 1
Write-Host -Object 'ERRORS!'
foreach ($record in $records) {
Write-Host -Object " - line $($record.Line): $($record.RuleName))`n $($record.Message)`n"
}
Write-Host -Object ''
}
}
exit $rc
-
name: Persist cache
if: always() && steps.restore-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
path: downloads
versions:
name: Resolve versions
outputs:
cygwin-mirror: ${{ steps.resolve.outputs.cygwin-mirror }}
cldr-version: ${{ steps.resolve.outputs.cldr-version }}
iconv-version: ${{ steps.resolve.outputs.iconv-version }}
iconv-version-base: ${{ steps.resolve.outputs.iconv-version-base }}
iconv-tarball-from-commit: ${{ steps.resolve.outputs.iconv-tarball-from-commit }}
iconv-source-url: ${{ steps.resolve.outputs.iconv-source-url }}
curl-version-default: ${{ steps.resolve.outputs.curl-version }}
json-c-version-default: ${{ steps.resolve.outputs.json-c-version }}
gettext-version: ${{ steps.resolve.outputs.gettext-version }}
gettext-source-url: ${{ steps.resolve.outputs.gettext-source-url }}
signpath-signing-policy-default: ${{ steps.resolve.outputs.signpath-signing-policy }}
signpath-artifactconfiguration-files: ${{ steps.resolve.outputs.signpath-artifactconfiguration-files }}
signatures-canbeinvalid: ${{ steps.resolve.outputs.signatures-canbeinvalid }}
release-tag: ${{ steps.resolve.outputs.release-tag }}
is-prerelease: ${{ steps.resolve.outputs.is-prerelease }}
runs-on: windows-2022
steps:
-
name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: ${{ github.event_name == 'pull_request' && '0' || '1' }}
-
name: Resolve
id: resolve
shell: pwsh
run: >
./service/resolve-versions.ps1
-CLDRVersion '${{ github.event.inputs.cldr-version }}'
-IconvVersion '${{ github.event.inputs.iconv-version }}'
-CurlVersion '${{ github.event.inputs.curl-version }}'
-JsonCVersion '${{ github.event.inputs.json-c-version }}'
-GettextVersion '${{ github.event.inputs.gettext-version }}'
-Sign '${{ github.event.inputs.sign }}'
-PublishRelease ${{ github.event.inputs.publish-release == 'true' && '$true' || '$false' }}
build-iconv-tarball:
name: Build iconv tarball
needs:
- versions
outputs:
artifact-id: ${{ steps.upload.outputs.artifact-id }}
runs-on: ubuntu-latest
container:
image: debian:trixie
steps:
-
name: Create directory structure
if: needs.versions.outputs.iconv-tarball-from-commit
run: mkdir output
-
name: Restore cache
if: needs.versions.outputs.iconv-tarball-from-commit
id: restore-cache
uses: actions/cache/restore@v5
with:
key: build-iconv-${{ needs.versions.outputs.iconv-tarball-from-commit }}
path: output
-
name: Check tarball existence
if: needs.versions.outputs.iconv-tarball-from-commit
id: check-tarball
run: |
if [ -f output/libiconv-${{ needs.versions.outputs.iconv-version }}.tar.gz ]; then
echo 'Tarball already exists in cache.'
echo 'build=no' >>"$GITHUB_OUTPUT"
else
echo 'Tarball not found in cache. Will build it.'
echo 'build=yes' >>"$GITHUB_OUTPUT"
fi
-
name: Update system
if: steps.check-tarball.outputs.build == 'yes'
run: |
apt-get update -q
apt-get upgrade -qy
-
name: Install system dependencies
if: steps.check-tarball.outputs.build == 'yes'
run: >
apt-get install -qy --no-install-recommends
ca-certificates git curl xz-utils make python3 patch autoconf gcc libc6-dev gperf groff gettext
-
name: Install automake
if: steps.check-tarball.outputs.build == 'yes'
working-directory: /tmp
run: |
curl -sSL https://ftp.gnu.org/gnu/automake/automake-1.18.1.tar.xz | tar -xJ
cd automake-*
./configure
make install
-
name: Download iconv source code
if: steps.check-tarball.outputs.build == 'yes'
run: git clone https://git.savannah.gnu.org/git/libiconv.git
-
name: Checkout commit ${{ needs.versions.outputs.iconv-tarball-from-commit }}
if: steps.check-tarball.outputs.build == 'yes'
working-directory: libiconv
run: git checkout ${{ needs.versions.outputs.iconv-tarball-from-commit }}
-
name: Pull git dependencies
if: steps.check-tarball.outputs.build == 'yes'
working-directory: libiconv
run: ./autopull.sh --one-time
-
name: Autogenerate build system
if: steps.check-tarball.outputs.build == 'yes'
working-directory: libiconv
run: ./autogen.sh
-
name: Configure
if: steps.check-tarball.outputs.build == 'yes'
working-directory: libiconv
run: ./configure
-
name: Build tarball
if: steps.check-tarball.outputs.build == 'yes'
working-directory: libiconv
run: make dist VERSION=${{ needs.versions.outputs.iconv-version }}
-
name: Copy tarball to output
if: steps.check-tarball.outputs.build == 'yes'
run: cp libiconv/libiconv-${{ needs.versions.outputs.iconv-version }}.tar.gz output/
-
name: Persist cache
if: steps.check-tarball.outputs.build == 'yes' && steps.restore-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
path: output
-
name: Upload tarball
if: needs.versions.outputs.iconv-tarball-from-commit
id: upload
uses: actions/upload-artifact@v6
with:
name: tarball-iconv
path: output/libiconv-${{ needs.versions.outputs.iconv-version }}.tar.gz
if-no-files-found: error
retention-days: 1
build:
name: ${{ matrix.bits}}-bit ${{ matrix.link }} w/ ${{ matrix.compiler }}
needs:
- test-bash-scripts
- test-pwsh-scripts
- versions
- build-iconv-tarball
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
include:
- bits: 32
link: shared
compiler: gcc
- bits: 32
link: static
compiler: gcc
- bits: 64
link: shared
compiler: gcc
- bits: 64
link: static
compiler: gcc
- bits: 32
link: shared
compiler: msvc
- bits: 32
link: static
compiler: msvc
- bits: 64
link: shared
compiler: msvc
- bits: 64
link: static
compiler: msvc
env:
CYGWIN_NOWINPATH: 1
CHERE_INVOKING: 1
defaults:
run:
shell: D:\cygwin\bin\bash.exe --login -o igncr -o errexit -o pipefail {0}
steps:
-
name: Configure git
shell: cmd
run: git config --global core.autocrlf input
-
name: Checkout
uses: actions/checkout@v6
-
name: Create directory structure
shell: pwsh
run: |
New-Item -ItemType Directory -Force -ErrorAction Stop -Path @(
'src/downloads'
'installed/bin'
'installed/include'
'installed/lib'
'installed/licenses'
'output-exe'
'output-dev'
'assets'
) | Out-Null
-
name: Restore cache
id: restore-cache
uses: actions/cache/restore@v5
with:
key: build-${{ matrix.link }}-${{ matrix.bits }}-${{ matrix.compiler }}
path: |
src\downloads
D:\cygwin-packages
-
name: Set variables
id: vars
shell: pwsh
run: >
./service/case-vars.ps1
-Bits ${{ matrix.bits }}
-Link ${{ matrix.link }}
-Compiler ${{ matrix.compiler }}
-InstalledPath installed
-ToolsPath src\downloads
-CLDRVersion '${{ needs.versions.outputs.cldr-version }}'
-IconvVersion '${{ needs.versions.outputs.iconv-version }}'
-CurlVersionDefault '${{ needs.versions.outputs.curl-version-default }}'
-JsonCVersionDefault '${{ needs.versions.outputs.json-c-version-default }}'
-GettextVersion '${{ needs.versions.outputs.gettext-version }}'
-SignpathSigningPolicyDefault '${{ needs.versions.outputs.signpath-signing-policy-default }}'
-
name: Install Cygwin
uses: cygwin/cygwin-install-action@v6
timeout-minutes: 60
with:
packages: ${{ steps.vars.outputs.cygwin-packages }}
install-dir: D:\cygwin
work-vol: 'D:'
site: ${{ needs.versions.outputs.cygwin-mirror }}
add-to-path: false
-
name: Setup Cygwin environment
run: |
PATH='${{ steps.vars.outputs.cygwin-path }}'
cd -- "$(cygpath -ua '${{ github.workspace }}')"
cp ./LICENSE.txt installed/license.txt
mkdir -p "$HOME"
printf "\nPATH='${{ steps.vars.outputs.cygwin-path }}'\nexport PATH\n" >>$HOME/.bash_profile
-
name: Dump Cygwin environment
run: |
printf 'Current working directory: %s\n' "$(pwd)"
echo 'PATH contains:'
IFS=:
for p in $PATH; do
printf -- '- %s\n' "$p"
done
-
name: Download FSF ar-lib
if: matrix.compiler == 'msvc'
shell: pwsh
run: >
./service/download-archive.ps1
-Url 'https://git.savannah.gnu.org/gitweb/?p=automake.git;a=blob_plain;f=lib/ar-lib;hb=HEAD'
-LocalFilePath src\downloads\ar-lib
-
name: Download FSF compile
if: matrix.compiler == 'msvc'
shell: pwsh
run: >
./service/download-archive.ps1
-Url 'https://git.savannah.gnu.org/gitweb/?p=automake.git;a=blob_plain;f=lib/compile;hb=HEAD'
-LocalFilePath src\downloads\compile
-
name: Download CLDR
shell: pwsh
run: >
./service/download-archive.ps1
-Url https://unicode.org/Public/cldr/${{ needs.versions.outputs.cldr-version }}/core.zip
-LocalFilePath src\downloads\cldr-${{ needs.versions.outputs.cldr-version }}.zip
-
name: Download iconv artifact
if: needs.versions.outputs.iconv-tarball-from-commit
uses: actions/download-artifact@v7
with:
artifact-ids: ${{ needs.build-iconv-tarball.outputs.artifact-id }}
path: src/downloads/
-
name: Download iconv
if: ${{ !needs.versions.outputs.iconv-tarball-from-commit }}
shell: pwsh
run: >
./service/download-archive.ps1
-Url '${{ needs.versions.outputs.iconv-source-url }}'
-LocalFilePath src\downloads\libiconv-${{ needs.versions.outputs.iconv-version }}.tar.gz
-
name: Download curl
if: steps.vars.outputs.curl-version
shell: pwsh
run: >
./service/download-archive.ps1
-Url https://curl.se/download/curl-${{ steps.vars.outputs.curl-version }}.tar.gz
-LocalFilePath src\downloads\curl-${{ steps.vars.outputs.curl-version }}.tar.gz
-
name: Download JSON-C
if: steps.vars.outputs.json-c-version
shell: pwsh
run: >
./service/download-archive.ps1
-Url https://s3.amazonaws.com/json-c_releases/releases/json-c-${{ steps.vars.outputs.json-c-version }}-nodoc.tar.gz
-LocalFilePath src\downloads\json-c-${{ steps.vars.outputs.json-c-version }}.tar.gz
-
name: Download gettext
shell: pwsh
run: >
./service/download-archive.ps1
-Url '${{ needs.versions.outputs.gettext-source-url }}'
-LocalFilePath src\downloads\gettext-${{ needs.versions.outputs.gettext-version }}.tar.gz
-
name: Add GCC Runtime license
if: matrix.compiler == 'gcc'
run: |
cp /usr/share/doc/mingw64-${{ steps.vars.outputs.mingw-architecture }}-gcc/COPYING installed/licenses/gcc.txt
-
name: Extract CLDR
run: |
unzip -p src/downloads/cldr-${{ needs.versions.outputs.cldr-version }}.zip LICENSE > installed/licenses/cldr.txt
mkdir -p installed/share/gettext/cldr/common/supplemental
unzip -p src/downloads/cldr-${{ needs.versions.outputs.cldr-version }}.zip common/supplemental/plurals.xml >installed/share/gettext/cldr/common/supplemental/plurals.xml
-
name: Simplify CLDR plurals.xml
if: steps.vars.outputs.cldr-simplify-plurals-xml == 'yes'
shell: pwsh
run: ./service/simplify-plurals-xml.ps1 installed/share/gettext/cldr/common/supplemental/plurals.xml
-
name: Extract iconv
run: |
tar x -C src -z -f src/downloads/libiconv-${{ needs.versions.outputs.iconv-version }}.tar.gz
cp src/libiconv-${{ needs.versions.outputs.iconv-version }}/COPYING installed/licenses/iconv.txt
-
name: Extract curl
if: steps.vars.outputs.curl-version
run: |
tar x -C src -z -f src/downloads/curl-${{ steps.vars.outputs.curl-version }}.tar.gz
cp src/curl-${{ steps.vars.outputs.curl-version }}/COPYING installed/licenses/curl.txt
-
name: Extract JSON-C
if: steps.vars.outputs.json-c-version
run: |
tar x -C src -z -f src/downloads/json-c-${{ steps.vars.outputs.json-c-version }}.tar.gz
cp src/json-c-${{ steps.vars.outputs.json-c-version }}/COPYING installed/licenses/json-c.txt
-
name: Extract gettext
run: |
tar x -C src -z -f src/downloads/gettext-${{ needs.versions.outputs.gettext-version }}.tar.gz
cp src/gettext-${{ needs.versions.outputs.gettext-version }}/COPYING installed/licenses/gettext.txt
-
name: Apply patches
run: |
set -o errexit
for dir in $(find src/* -maxdepth 1 -type d -printf '%f\n'); do
if ! test -d "patches/$dir"; then
continue
fi
printf 'Applying patches for %s\n' "$dir"
for patchfile in $(find patches/$dir -maxdepth 1 -type f -printf '%f\n' | sort); do
printf -- '- %s\n' "$patchfile"
patch -d "src/$dir" -p1 -u <"patches/$dir/$patchfile"
done
done
-
name: Configure iconv (1st time)
id: iconv-configure
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: |
mkdir build
cd build
../configure ${{ steps.vars.outputs.iconv-configure-args }}
-
name: Compile iconv (1st time)
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc)
-
name: Check iconv (1st time)
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) check
-
name: Install iconv (1st time)
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
name: Configure curl
if: steps.vars.outputs.curl-version
id: curl-configure
working-directory: src\curl-${{ steps.vars.outputs.curl-version }}
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: |
mkdir build
cd build
../configure ${{ steps.vars.outputs.curl-configure-args }}
if [ "$(./curl-config --built-shared)" = yes ]; then
libs="$(./curl-config --libs)"
else
libs="$(./curl-config --static-libs)"
fi
echo "libs=$libs" >>"$GITHUB_OUTPUT"
echo 'OUTPUTS:'
cat "$GITHUB_OUTPUT"
-
name: Install curl - libcurl
if: steps.vars.outputs.curl-version
working-directory: src\curl-${{ steps.vars.outputs.curl-version }}\build\lib
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
name: Install curl - include
if: steps.vars.outputs.curl-version
working-directory: src\curl-${{ steps.vars.outputs.curl-version }}\build\include
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
name: Prepare JSON-C
if: steps.vars.outputs.json-c-version
working-directory: src\json-c-${{ steps.vars.outputs.json-c-version }}
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: |
mkdir build
cd build
cmake ${{ steps.vars.outputs.json-c-cmake-args }} \
../
-
name: Build JSON-C
if: steps.vars.outputs.json-c-version
working-directory: src\json-c-${{ steps.vars.outputs.json-c-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) all
-
name: Install JSON-C
if: steps.vars.outputs.json-c-version
working-directory: src\json-c-${{ steps.vars.outputs.json-c-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make install/strip
-
name: Configure gettext
id: gettext-configure
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: |
mkdir build
cd build
../configure \
LIBS='${{ steps.curl-configure.outputs.libs }}' ${{ steps.vars.outputs.gettext-configure-args }}
-
name: Ignore gettext C tests
if: steps.vars.outputs.gettext-ignore-c-tests
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}
run: for f in ${{ steps.vars.outputs.gettext-ignore-c-tests }}; do echo 'int main() { return 0; }' >$f; done
-
name: Compile gettext/gnulib-local
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gnulib-local
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc)
-
name: Check gettext/gnulib-local
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gnulib-local
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) check
-
name: Install gettext/gnulib-local
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gnulib-local
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
name: Compile gettext/gettext-runtime
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gettext-runtime
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc)
-
name: Check gettext/gettext-runtime
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gettext-runtime
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) check
-
name: Install gettext/gettext-runtime
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gettext-runtime
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
name: Compile gettext/libtextstyle
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\libtextstyle
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc)
-
name: Check gettext/libtextstyle
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\libtextstyle
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) check
-
name: Install gettext/libtextstyle
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\libtextstyle
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
name: Compile gettext/gettext-tools
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gettext-tools
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc)
-
name: Check gettext/gettext-tools
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gettext-tools
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: XFAIL_TESTS='${{ steps.vars.outputs.gettext-xfail-gettext-tools }}' make --jobs=$(nproc) check
-
name: Install gettext/gettext-tools
working-directory: src\gettext-${{ needs.versions.outputs.gettext-version }}\build\gettext-tools
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
# We need to rebuild iconv because it depends on gettext's libintl in order to be localizable
name: Configure iconv (2nd time)
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: |
rm -rf build
mkdir build
cd build
../configure ${{ steps.vars.outputs.iconv-configure-args }} \
--enable-extra-encodings
-
name: Compile iconv (2nd time)
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc)
-
name: Check iconv (2nd time)
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) check
-
name: Install iconv (2nd time)
working-directory: src\libiconv-${{ needs.versions.outputs.iconv-version }}\build
env:
INCLUDE: ${{ steps.vars.outputs.include-env-var }}
LIB: ${{ steps.vars.outputs.lib-env-var }}
run: make --jobs=$(nproc) ${{ steps.vars.outputs.make-install-argument }}
-
name: Finalize install dir
shell: pwsh
run: >
./service/finalize-installed.ps1
-Bits ${{ matrix.bits }}
-Link ${{ matrix.link }}
-Path installed
-MinGWPath ${{ matrix.compiler == 'mscv' && '' || format('D:\\cygwin\\usr\\{0}', steps.vars.outputs.mingw-host) }}
-
name: Extract version infos
id: versioninfos
shell: pwsh
run: ./service/extract-versiononfos.ps1 -RootPath installed
-
name: Check bitness
run: ./service/check-bits.sh ${{ matrix.bits }} installed
-
name: Upload unsigned files
if: steps.vars.outputs.signpath-signing-policy
id: upload-installed-unsigned
uses: actions/upload-artifact@v6
with:
name: tobesigned-installed-${{ matrix.link }}-${{ matrix.bits }}-${{ matrix.compiler }}
path: |
installed/**/*.dll
installed/**/*.exe
if-no-files-found: error
retention-days: 1
-
name: Sign files
if: steps.vars.outputs.signpath-signing-policy
id: sign-files
uses: signpath/github-action-submit-signing-request@v2
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: 98c3accc-92c9-4962-b150-ff1f5c6356b8
project-slug: gettext-iconv-windows
signing-policy-slug: '${{ steps.vars.outputs.signpath-signing-policy }}'
artifact-configuration-slug: ${{ needs.versions.outputs.signpath-artifactconfiguration-files }}
github-artifact-id: ${{ steps.upload-installed-unsigned.outputs.artifact-id }}
wait-for-completion: true
output-artifact-directory: installed
parameters: ${{ steps.versioninfos.outputs.signpath-parameters }}
-
name: Check signatures
if: steps.vars.outputs.signpath-signing-policy
shell: pwsh
run: >
./service/check-signature.ps1
-GettextVersion ${{ needs.versions.outputs.gettext-version }}
-Path installed
-CanBeInvalid ${{ needs.versions.outputs.signatures-canbeinvalid == 'yes' && '$true' || '$false' }}
-
name: Copy built developer files
shell: pwsh
run: ./service/copy-output.ps1 -Type dev -From installed -To output-dev
-
name: Create developer files archive
shell: pwsh
working-directory: output-dev
run: |
& 7z.exe a -bd -bt -mx9 -r -sse -tzip ..\assets\gettext${{ needs.versions.outputs.gettext-version }}-iconv${{ needs.versions.outputs.iconv-version-base }}-${{ matrix.link }}-${{ matrix.bits }}-dev-${{ matrix.compiler }}.zip
-
name: Copy built executables
shell: pwsh
run: ./service/copy-output.ps1 -Type exe -From installed -To output-exe
-
name: Delete unused dependencies
shell: pwsh
run: ./service/delete-unused-dependencies.ps1 -Bits ${{ matrix.bits }} -Link ${{ matrix.link }} -Path output-exe
-
name: Create executable files archive
if: steps.vars.outputs.collect-programs == 'yes'
shell: pwsh
working-directory: output-exe
run: |
& 7z.exe a -bd -bt -mx9 -r -sse -tzip ..\assets\gettext${{ needs.versions.outputs.gettext-version }}-iconv${{ needs.versions.outputs.iconv-version-base }}-${{ matrix.link }}-${{ matrix.bits }}.zip
-
name: Prepare build log
id: prepare-build-log
if: (success() || failure()) && (steps.iconv-configure.outcome == 'success' || steps.iconv-configure.outcome == 'failure')
run: |
mkdir build-log
if [ -d src/libiconv-${{ needs.versions.outputs.iconv-version }}/build ]; then
tar c -J -f build-log/iconv.tar.xz src/libiconv-${{ needs.versions.outputs.iconv-version }}/build
fi
if [ -d src/curl-${{ steps.vars.outputs.curl-version }}/build ]; then
tar c -J -f build-log/curl.tar.xz src/curl-${{ steps.vars.outputs.curl-version }}/build
fi
if [ -d src/json-c-${{ steps.vars.outputs.json-c-version }}/build ]; then
tar c -J -f build-log/json-c.tar.xz src/json-c-${{ steps.vars.outputs.json-c-version }}/build
fi
if [ -d src/gettext-${{ needs.versions.outputs.gettext-version }}/build ]; then
tar c -J -f build-log/gettext.tar.xz src/gettext-${{ needs.versions.outputs.gettext-version }}/build
fi
if [ -d installed ]; then
if find installed -mindepth 1 -maxdepth 1 | read; then
tar c -J -f build-log/installed.tar.xz installed
fi
fi
ls -al build-log
-
name: Delete install directory
run: rm -rf installed
-
name: Check if iconv program load translations correctly
shell: pwsh
run: |
$env:LANGUAGE = 'it'
$stdout = & .\output-exe\bin\iconv.exe --help
if (-not($?)) {
throw "iconv.exe failed"
}
$stdout = $stdout -join "`n"
if (!$stdout.Contains('formato di input')) {
throw "iconv.exe didn't load the translations.`nIts output is:`n$stdout"
}
Write-Host "iconv.exe correctly loaded the translations when LANGUAGE=$env:LANGUAGE`nIts localized output is`n$stdout"
-
name: Check if gettext programs load translations correctly
shell: pwsh
run: |
$env:LANGUAGE = 'it'
$stdout = & .\output-exe\bin\xgettext.exe --help
if (-not($?)) {
throw "xgettext.exe failed"
}
$stdout = $stdout -join "`n"
if (!$stdout.Contains('impostazione predefinita')) {
throw "xgettext.exe didn't load the translations.`nIts output is:`n$stdout"
}
Write-Host "xgettext.exe correctly loaded the translations when LANGUAGE=$env:LANGUAGE`nIts localized output is`n$stdout"
-
name: Check cldr-plurals
shell: pwsh
run: |
$pot = @'
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Hi"
msgstr ""
'@
$lang = 'zu'
Remove-Item -LiteralPath Env:GETTEXTCLDRDIR -ErrorAction SilentlyContinue
$po = $pot | & .\output-exe\bin\msginit.exe --input=- --output-file=- --locale="$lang"
$rule = $po -match "Plural-Forms:"
if ($rule) {
throw "Without GETTEXTCLDRDIR there shouldn't be a Plural-Forms header in the .po file for the locale $lang, but we found it: $rule"
}
Write-Output -InputObject "As expected, without GETTEXTCLDRDIR there isn't a Plural-Forms header in the .po file for the locale $lang."
$env:GETTEXTCLDRDIR = "$PWD\output-exe\share\gettext\cldr"
$po = $pot | & .\output-exe\bin\msginit.exe --input=- --output-file=- --locale="$lang"
$rule = $po -match "Plural-Forms:"
if ('${{ steps.vars.outputs.cldr-plural-works }}' -eq 'yes') {
if (-not($rule)) {
throw "With GETTEXTCLDRDIR there should be a Plural-Forms header in the .po file for the locale $lang, but there isn't."
}
Write-Output -InputObject "With GETTEXTCLDRDIR there is a Plural-Forms header ($rule) in the .po file for the locale $lang."
} else {
if ($rule) {
throw "Even with GETTEXTCLDRDIR there shouldn't be a Plural-Forms header in the .po file for the locale $lang, but we found it: $rule"
}
Write-Output -InputObject "As expected, even with GETTEXTCLDRDIR there isn't a Plural-Forms header in the .po file for the locale $lang."
}
-
name: Start fake ollama server
if: steps.vars.outputs.check-spit-exe == 'yes'
id: start-fake-ollama-server
shell: pwsh
run: |
$process = Start-Process pwsh -ArgumentList '.\service\run-fake-ollama-server.ps1' -WindowStyle Hidden -PassThru
Start-Sleep -Seconds 2
$process.Refresh()
if ($process.HasExited) {
throw 'Failed to start fake ollama server'
}
Write-Host "Started fake ollama server (process ID: $($process.Id))"
"pid=$($process.Id)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
-
name: Check spit executable
if: steps.vars.outputs.check-spit-exe == 'yes'
shell: pwsh
run: |
$spitPath = '.\output-exe\bin\spit.exe'
if (-not(Test-Path -LiteralPath $spitPath -PathType Leaf)) {
throw "spit.exe not found at expected path: $spitPath"
}
$stdout = Write-Output 'Test' | & $spitPath --model=llama3.2:3b --to=fr
if (-not($?)) {
throw "spit.exe failed"
}
$stdout = $stdout -join "`n"
if ($stdout -ne "Ollama answer to prompt Translate into French:`nTest") {
throw "spit.exe output is unexpected.`nIts output is:`n$stdout"
}
Write-Host "spit.exe executed correctly.`nIts output is`n$stdout"
-
name: Stop fake ollama server
if: (success() || failure()) && steps.start-fake-ollama-server.outcome == 'success'
shell: pwsh
run: |
try {
$process = Get-Process -Id ${{ steps.start-fake-ollama-server.outputs.pid }}
} catch {
$process = $null
}
if ($null -ne $process) {
$process.Kill($true)
}
-
name: Create installer
if: steps.vars.outputs.collect-programs == 'yes'
shell: pwsh
run: >
./service/create-installer.ps1
-Bits ${{ matrix.bits }}
-Link ${{ matrix.link }}
-SourceDirectory output-exe
-OutputDirectory assets
-IconvVersion ${{ needs.versions.outputs.iconv-version-base }}
-GettextVersion ${{ needs.versions.outputs.gettext-version }}
-
name: Check bitness
if: steps.vars.outputs.collect-programs == 'yes'
run: ./service/check-bits.sh 32 assets/gettext${{ needs.versions.outputs.gettext-version }}-iconv${{ needs.versions.outputs.iconv-version-base }}-${{ matrix.link }}-${{ matrix.bits }}.exe
-
name: Upload unsigned installer
if: steps.vars.outputs.collect-programs == 'yes' && steps.vars.outputs.signpath-signing-policy
id: upload-installer-unsigned
uses: actions/upload-artifact@v6
with:
name: tobesigned-installer-${{ matrix.link }}-${{ matrix.bits }}-${{ matrix.compiler }}
path: assets/gettext${{ needs.versions.outputs.gettext-version }}-iconv${{ needs.versions.outputs.iconv-version-base }}-${{ matrix.link }}-${{ matrix.bits }}.exe
if-no-files-found: error
compression-level: 0
retention-days: 1
-
name: Sign installer
if: steps.vars.outputs.collect-programs == 'yes' && steps.vars.outputs.signpath-signing-policy
id: sign-installer
uses: signpath/github-action-submit-signing-request@v2
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: 98c3accc-92c9-4962-b150-ff1f5c6356b8
project-slug: gettext-iconv-windows
signing-policy-slug: '${{ steps.vars.outputs.signpath-signing-policy }}'
artifact-configuration-slug: gh_sign_installer
github-artifact-id: ${{ steps.upload-installer-unsigned.outputs.artifact-id }}
wait-for-completion: true
output-artifact-directory: assets
-
name: Check signature
if: steps.vars.outputs.collect-programs == 'yes' && steps.vars.outputs.signpath-signing-policy
shell: pwsh
run: >
./service/check-signature.ps1
-GettextVersion ${{ needs.versions.outputs.gettext-version }}
-Path assets/gettext${{ needs.versions.outputs.gettext-version }}-iconv${{ needs.versions.outputs.iconv-version-base }}-${{ matrix.link }}-${{ matrix.bits }}.exe
-CanBeInvalid ${{ needs.versions.outputs.signatures-canbeinvalid == 'yes' && '$true' || '$false' }}
-
name: Upload assets
uses: actions/upload-artifact@v6
with:
name: assets-${{ matrix.link }}-${{ matrix.bits }}-${{ matrix.compiler }}
path: assets/*
if-no-files-found: error
compression-level: 0
-
name: Upload build log
if: always() && steps.prepare-build-log.outcome == 'success'
uses: actions/upload-artifact@v6
with:
name: log-${{ matrix.link }}-${{ matrix.bits }}-${{ matrix.compiler }}
if-no-files-found: ignore
retention-days: 1
include-hidden-files: true
compression-level: 0
path: build-log
-
name: Persist cache
if: always() && steps.restore-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
path: |
src\downloads
D:\cygwin-packages
publish-release:
name: Publish release
needs:
- versions
- build
if: needs.versions.outputs.release-tag
runs-on: ubuntu-latest
steps:
-
name: Create assets directory
run: mkdir -p assets
-
name: Download assets
uses: actions/download-artifact@v7
with:
path: assets
pattern: assets-*
merge-multiple: true
-
name: Publish release
uses: softprops/action-gh-release@v2
with:
name: ${{ needs.versions.outputs.release-tag }}
tag_name: ${{ needs.versions.outputs.release-tag }}
files: assets/*
fail_on_unmatched_files: true
prerelease: ${{ needs.versions.outputs.is-prerelease == 'yes' && 'true' || 'false' }}
make_latest: ${{ needs.versions.outputs.is-prerelease == 'yes' && 'false' || 'true' }}
body: |
## Components
* gettext ${{ needs.versions.outputs.gettext-version }}
* iconv ${{ needs.versions.outputs.iconv-version-base }}
* libcurl ${{ needs.versions.outputs.curl-version-default }}
* libjson-c ${{ needs.versions.outputs.json-c-version-default }}
* CLDR ${{ needs.versions.outputs.cldr-version }}
generate_release_notes: true