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

catch install-time errors on windows #553

Merged
merged 16 commits into from
Aug 16, 2022
19 changes: 16 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,31 @@ jobs:
# and upload them all to anaconda.org in a single job
name: package-${{ github.sha }}
path: ${{ runner.temp }}/conda-bld/*/*.tar.bz2
- name: Run examples and prepare artifacts
- name: Install local constructor
run: |
source ../conda/etc/profile.d/conda.sh
CONDA_BLD_PATH="${{ runner.temp }}/conda-bld" \
conda create -n constructor -c local --strict-channel-priority constructor
conda activate constructor
installed_channel=$(conda list --json | jq -r '.[] | select(.name=="constructor") | .channel')
installed_channel=$(conda list constructor --json | jq -r '.[].channel')
if [[ "$installed_channel" != "conda-bld" ]]; then
echo $(conda list --json | jq '.[] | select(.name=="constructor")')
echo $(conda list constructor --json)
echo "Installed constructor is not local!"
exit 1
fi
- name: Patch NSIS to use logging builds on Windows
if: startsWith(matrix.os, 'windows')
run: |
source ../conda/etc/profile.d/conda.sh
conda activate constructor
nsis_version=$(conda list nsis --json | jq -r ".[].version")
curl -sL "https://sourceforge.net/projects/nsis/files/NSIS%203/${nsis_version}/nsis-${nsis_version}-log.zip/download" -o "nsis-${nsis_version}-log.zip"
7z x "nsis-${nsis_version}-log.zip" -aoa -o"$CONDA_PREFIX/NSIS/"
echo "NSIS_USING_LOG_BUILD=1" >> $GITHUB_ENV
- name: Run examples and prepare artifacts
run: |
source ../conda/etc/profile.d/conda.sh
conda activate constructor
mkdir -p examples_artifacts/
python scripts/run_examples.py --keep-artifacts=examples_artifacts/
- name: Upload the example installers as artifacts
Expand Down
36 changes: 35 additions & 1 deletion constructor/nsis/main.nsi.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@

Unicode "true"

#if enable_debugging is True
# Special logging build needed for ENABLE_LOGGING
# See https://nsis.sourceforge.io/Special_Builds
!define ENABLE_LOGGING
#endif

# Comes from https://nsis.sourceforge.io/Logging:Enable_Logs_Quickly
!define LogSet "!insertmacro LogSetMacro"
!macro LogSetMacro SETTING
!ifdef ENABLE_LOGGING
LogSet ${SETTING}
!endif
!macroend

!define LogText "!insertmacro LogTextMacro"
!macro LogTextMacro INPUT_TEXT
!ifdef ENABLE_LOGGING
LogText ${INPUT_TEXT}
!endif
!macroend

!include "WinMessages.nsh"
!include "WordFunc.nsh"
!include "LogicLib.nsh"
Expand Down Expand Up @@ -414,6 +435,7 @@ Function InstModePage_Leave
FunctionEnd

Function .onInit
${LogSet} on
Push $0
Push $1
Push $2
Expand Down Expand Up @@ -835,6 +857,7 @@ Function AbortRetryNSExecWait
nsExec::ExecToLog $2
pop $0
${If} $0 != "0"
DetailPrint "::error:: $1"
MessageBox MB_ABORTRETRYIGNORE|MB_ICONEXCLAMATION|MB_DEFBUTTON3 \
$1 /SD IDIGNORE IDABORT abort IDRETRY retry
; IDIGNORE: Continue anyway
Expand All @@ -851,6 +874,7 @@ FunctionEnd

# Installer sections
Section "Install"
${LogSet} on

SetOutPath "$INSTDIR\Lib"
File "@NSIS_DIR@\_nsis.py"
Expand Down Expand Up @@ -893,6 +917,13 @@ Section "Install"

@PKG_COMMANDS@

SetDetailsPrint TextOnly
DetailPrint "Setting up the package cache ..."
push '"$INSTDIR\_conda.exe" constructor --prefix "$INSTDIR" --extract-conda-pkgs'
push 'Failed to extract packages'
call AbortRetryNSExecWait
SetDetailsPrint both

@SETUP_ENVS@

@WRITE_CONDARC@
Expand All @@ -906,9 +937,12 @@ Section "Install"
call AbortRetryNSExecWait
${EndIf}

#if has_conda is True
DetailPrint "Initializing conda directories..."
push '"$INSTDIR\pythonw.exe" -E -s "$INSTDIR\Lib\_nsis.py" mkdirs'
push 'Failed to initialize Anaconda directories'
push 'Failed to initialize conda directories'
call AbortRetryNSExecWait
#endif

${If} $Ana_PostInstall_State = ${BST_CHECKED}
DetailPrint "Running post install..."
Expand Down
14 changes: 10 additions & 4 deletions constructor/winexe.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,25 +68,29 @@ def setup_envs_commands(info, dir_path):
SetDetailsPrint both
# List of packages to install
SetOutPath "{env_txt_dir}"
File {env_txt_abspath}
File "{env_txt_abspath}"
# A conda-meta\history file is required for a valid conda prefix
SetOutPath "{conda_meta}"
FileOpen $0 "history" w
FileClose $0
File "{history_abspath}"
# Set channels
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_CHANNELS", "{channels}").r0'
# Run conda
SetDetailsPrint TextOnly
nsExec::ExecToLog '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" {shortcuts}'
Pop $0
${{If}} $0 != "0"
DetailPrint "::error:: Failed to link extracted packages to {prefix}!"
MessageBox MB_OK|MB_ICONSTOP "Failed to link extracted packages to {prefix}. Please check logs." /SD IDOK
Abort
${{EndIf}}
SetDetailsPrint both
# Cleanup {name} env.txt
SetOutPath "$INSTDIR"
Delete "{env_txt}"
# Restore shipped conda-meta\history for remapped
# channels and retain only the first transaction
SetOutPath "{conda_meta}"
File {history_abspath}
File "{history_abspath}"
"""

lines = template.format( # this one block is for the base environment
Expand Down Expand Up @@ -194,6 +198,8 @@ def make_nsi(info, dir_path, extra_files=()):
ppd['keep_pkgs'] = info.get('keep_pkgs') or False
ppd['post_install_exists'] = bool(info.get('post_install'))
ppd['with_conclusion_text'] = bool(conclusion_text)
ppd["enable_debugging"] = bool(os.environ.get("NSIS_USING_LOG_BUILD"))
ppd["has_conda"] = info["_has_conda"]
data = preprocess(data, ppd)
data = fill_template(data, replace)
if info['_platform'].startswith("win") and sys.platform != 'win32':
Expand Down
25 changes: 25 additions & 0 deletions news/553-fix-windows-ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Enhancements:
-------------

* A single installer can now provide multiple environments through the `extra_envs` key (#359 via #509 and #553)

Bug fixes:
----------

* Windows CI now correctly detects installation problems (#551)

Deprecations:
-------------

* <news item>

Docs:
-----

* <news item>

Other:
------

* <news item>

8 changes: 8 additions & 0 deletions scripts/run_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ def run_examples(keep_artifacts=None):
elif ext == 'exe':
cmd = ['cmd.exe', '/c', 'start', '/wait', fpath, '/S', '/D=%s' % env_dir]
test_errored = _execute(cmd)
if ext == 'exe' and os.environ.get("NSIS_USING_LOG_BUILD"):
test_errored = 0
with open(os.path.join(env_dir, "install.log"), encoding="utf-16-le") as f:
print('--- LOGS ---')
for line in f:
if ":error:" in line:
print(line.rstrip())
test_errored = 1
errored += test_errored
if keep_artifacts:
shutil.move(fpath, keep_artifacts)
Expand Down