name: Build and test GAM on: push: paths-ignore: - 'wiki/**' pull_request: paths-ignore: - 'wiki/**' schedule: - cron: '37 22 * * *' workflow_dispatch: permissions: contents: read id-token: write attestations: write defaults: run: shell: bash working-directory: src env: SCRATCH_COUNTER: 14 OPENSSL_CONFIG_OPTS: no-fips --api=3.0.0 no-docs no-tls1 no-tls1_1 no-dtls no-comp no-srp no-psk no-nextprotoneg no-weak-ssl-ciphers no-idea no-seed no-camellia no-sm2 no-sm3 no-sm4 no-rc2 no-rc4 no-rc5 no-md2 no-md4 no-cast no-des no-shared -fPIC no-tests -O3 OPENSSL_INSTALL_PATH: ${{ github.workspace }}/bin/ssl OPENSSL_SOURCE_PATH: ${{ github.workspace }}/src/openssl PYTHON_INSTALL_PATH: ${{ github.workspace }}/bin/python PYTHON_SOURCE_PATH: ${{ github.workspace }}/src/cpython CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY: 1 CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1 WINDOWS_CODESIGN_CERT_HASH: 3B11D9340A45CF078FF7FD984F1C3E30DA82FD05 jobs: build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - os: ubuntu-22.04 jid: 1 freethreaded: false goal: build name: Build Intel Ubuntu Jammy - os: ubuntu-24.04 jid: 2 freethreaded: false goal: build name: Build Intel Ubuntu Noble - os: ubuntu-24.04-arm jid: 3 freethreaded: false goal: build name: Build Arm Ubuntu Noble - os: ubuntu-22.04-arm jid: 4 freethreaded: false goal: build name: Build Arm Ubuntu Jammy - os: ubuntu-22.04 jid: 5 freethreaded: false goal: build staticx: yes name: Build Intel StaticX Legacy - os: ubuntu-22.04-arm jid: 6 freethreaded: false goal: build staticx: yes name: Build Arm StaticX Legacy - os: macos-14 jid: 8 freethreaded: false goal: build name: Build Arm MacOS 14 - os: macos-15 jid: 9 freethreaded: false goal: build name: Build Arm MacOS 15 - os: macos-15-intel jid: 10 freethreaded: false goal: build name: Build x86_64 macOS 15 - os: macos-26-intel jid: 11 freethreaded: false goal: build name: Build x86_64 macOS 26 - os: macos-26 jid: 12 freethreaded: false goal: build name: Build Arm MacOS 26 - os: windows-2025-vs2026 jid: 13 freethreaded: false goal: build name: Build Intel Windows - os: windows-11-arm jid: 14 freethreaded: false goal: build name: Build Arm Windows - os: ubuntu-24.04 goal: test python: "3.10" freethreaded: false jid: 15 name: Test Python 3.10 - os: ubuntu-24.04 goal: test python: "3.11" freethreaded: false jid: 16 name: Test Python 3.11 - os: ubuntu-24.04 goal: test python: "3.12" freethreaded: false jid: 17 name: Test Python 3.12 - os: ubuntu-24.04 goal: test python: "3.13" freethreaded: false jid: 18 name: Test Python 3.13 - os: ubuntu-24.04 goal: test python: "3.15-dev" freethreaded: false jid: 19 name: Test Python 3.15-dev - os: ubuntu-24.04 goal: test python: "3.14" freethreaded: true jid: 20 name: Test Python 3.14 freethread steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false fetch-depth: 0 - id: auth name: Authenticate to Google Cloud uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0 with: workload_identity_provider: projects/297925809119/locations/global/workloadIdentityPools/gha-pool/providers/gha-provider service_account: github-actions-testing-for-gam@gam-project-wyo-lub-ivl.iam.gserviceaccount.com access_token_scopes: https://www.googleapis.com/auth/iam - name: Cache multiple paths if: matrix.goal == 'build' uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 id: cache-python-ssl with: path: | cache.tar.xz key: gam-${{ matrix.jid }}-20260523 - name: Untar Cache archive if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true' working-directory: ${{ github.workspace }} run: | tar xvvf cache.tar.xz - name: Use pre-compiled Python for testing if: matrix.python != '' uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} allow-prereleases: true check-latest: true freethreaded: ${{ matrix.freethreaded }} - name: common variables for all runs env: JID: ${{ matrix.jid }} ACTIONS_CACHE: ${{ steps.cache-python-ssl.outputs.cache-hit }} ACTIONS_GOAL: ${{ matrix.goal }} freethreaded: ${{ matrix.freethreaded }} run: | case $RUNNER_ARCH in X64) echo "arch=x86_64" >> $GITHUB_ENV ;; ARM64) echo "arch=arm64" >> $GITHUB_ENV ;; *) echo "arch=${RUNNER_ARCH}" >> $GITHUB_ENV ;; esac # calculate with python because date on MacOS is just stupid DEPS_CUTOFF=$(python3 -c "from datetime import datetime, timedelta, timezone; print((datetime.now(timezone.utc) - timedelta(days=14)).strftime('%Y-%m-%dT00:00:00Z'))") echo "DEPS_CUTOFF=${DEPS_CUTOFF}" >> $GITHUB_ENV echo "JID=${JID}" >> $GITHUB_ENV echo "freethreaded=${freethreaded}" >> $GITHUB_ENV if "$freethreaded"; then # Hush some warnings while we test export PYTHON_GIL=0 echo "PYTHON_GIL=${PYTHON_GIL}" >> $GITHUB_ENV fi echo "ACTIONS_CACHE=${ACTIONS_CACHE}" >> $GITHUB_ENV echo "ACTIONS_GOAL=${ACTIONS_GOAL}" >> $GITHUB_ENV curl_version=$(curl --version | head -n 1 | awk '{ print $2 }') echo "cURL is ${curl_version}" if [ "$curl_version" == "7.68.0" ]; then export curl_retry="--retry 5 --retry-connrefused" else export curl_retry="--retry 5 --retry-all-errors" fi echo "curl_retry=${curl_retry}" >> $GITHUB_ENV # GAMCFGDIR should be recreated on every run GAMCFGDIR="${RUNNER_TEMP}/.gam" if [ "$RUNNER_OS" == "Windows" ]; then GAMCFGDIR=$(cygpath -u "$GAMCFGDIR") fi echo "GAMCFGDIR=${GAMCFGDIR}" >> $GITHUB_ENV echo "GAMCFGDIR is: ${GAMCFGDIR}" export GAMOS=$(echo "$RUNNER_OS" | tr '[:upper:]' '[:lower:]') echo "GAMOS=${GAMOS}" >> $GITHUB_ENV echo "GAMOS is: ${GAMOS}" - name: Set env variables for test if: matrix.goal == 'test' run: | export PYTHON=$(which python3) export gampath="$(readlink -e .)/gam" echo -e "PYTHON: ${PYTHON}\ngam: ${gam}\ngampath: ${gampath}" echo "PYTHON=${PYTHON}" >> $GITHUB_ENV echo "gampath=${gampath}" >> $GITHUB_ENV - name: Install necessary Github-hosted Linux packages if: runner.os == 'Linux' run: | echo "RUNNING: apt update..." sudo apt-get -qq --yes update sudo apt-get -qq --yes install swig libpcsclite-dev libxslt1-dev libsqlite3-dev libffi-dev pkg-config - name: MacOS install tools if: runner.os == 'macOS' run: | # Install latest Rust curl $curl_retry -fsS -o rust.sh https://sh.rustup.rs bash ./rust.sh -y source $HOME/.cargo/env # Install needed packages #brew update #brew install gpg #brew install swig #brew install ncurses - name: MacOS import developer certificates for signing if: runner.os == 'macOS' uses: apple-actions/import-codesign-certs@b610f78488812c1e56b20e6df63ec42d833f2d14 # v6.0.0 with: p12-file-base64: ${{ secrets.CERTIFICATES_P12 }} p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }} - name: Windows Configure VCode uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 if: runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' with: arch: ${{ runner.arch }} - name: Set Env Variables for build if: matrix.goal == 'build' env: staticx: ${{ matrix.staticx }} run: | echo "We are running on ${RUNNER_OS}" LD_LIBRARY_PATH="${OPENSSL_INSTALL_PATH}/lib:${PYTHON_INSTALL_PATH}/lib:/usr/local/lib" if [[ "${RUNNER_OS}" == "macOS" ]]; then export CFLAGS="-O3 -pipe" export LDFLAGS="-Wl,-dead_strip" MAKE=make MAKEOPT="-j$(sysctl -n hw.logicalcpu)" PERL=perl MACOSX_DEPLOYMENT_TARGET=$(sw_vers -productVersion | awk -F '.' '{print $1 "." $2}') echo "MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}" >> $GITHUB_ENV echo "We are running on and targetting MacOS ${MACOSX_DEPLOYMENT_TARGET}" echo "PYTHON=${PYTHON_INSTALL_PATH}/bin/python3" >> $GITHUB_ENV elif [[ "${RUNNER_OS}" == "Linux" ]]; then export CFLAGS="-O3 -pipe" export LDFLAGS="-Wl,--strip-all" MAKE=make MAKEOPT="-j$(nproc)" PERL=perl echo "PYTHON=${PYTHON_INSTALL_PATH}/bin/python3" >> $GITHUB_ENV elif [[ "${RUNNER_OS}" == "Windows" ]]; then MAKE=nmake MAKEOPT="" PERL="c:\strawberry\perl\bin\perl.exe" if [[ "$RUNNER_ARCH" == "ARM64" ]]; then PYEXTERNALS_ARCH="arm64" WIX_ARCH="arm64" elif [[ "$RUNNER_ARCH" == "X64" ]]; then PYEXTERNALS_ARCH="amd64" WIX_ARCH="x64" fi PYEXTERNALS_PATH=$(cygpath -u "${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}") LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYEXTERNALS_PATH}" echo "PYTHON=${PYTHON_INSTALL_PATH}\python.exe" >> $GITHUB_ENV echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV echo "PS_PYTHON_INSTALL_PATH=$(cygpath -w $PYTHON_INSTALL_PATH)" >> $GITHUB_ENV fi echo "We'll run make with: ${MAKEOPT}" echo "staticx=${staticx}" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> $GITHUB_ENV echo "MAKE=${MAKE}" >> $GITHUB_ENV echo "MAKEOPT=${MAKEOPT}" >> $GITHUB_ENV echo "CFLAGS=${CFLAGS}" >> $GITHUB_ENV echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_ENV echo "PERL=${PERL}" >> $GITHUB_ENV echo "PYEXTERNALS_PATH=${PYEXTERNALS_PATH}" >> $GITHUB_ENV - name: Get latest stable OpenSSL source if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | mkdir -vp "${GITHUB_WORKSPACE}/src" cd "${GITHUB_WORKSPACE}/src" git clone https://github.com/openssl/openssl.git cd "${OPENSSL_SOURCE_PATH}" export LATEST_STABLE_TAG=$(git tag --list openssl-* | grep -v alpha | grep -v beta | sort -Vr | head -n1) echo "Checking out version ${LATEST_STABLE_TAG}" git checkout "${LATEST_STABLE_TAG}" export COMPILED_OPENSSL_VERSION=${LATEST_STABLE_TAG:8} # Trim the openssl- prefix echo "COMPILED_OPENSSL_VERSION=${COMPILED_OPENSSL_VERSION}" >> $GITHUB_ENV - name: Windows NASM Install uses: ilammy/setup-nasm@72793074d3c8cdda771dba85f6deafe00623038b # v1.5.2 if: matrix.goal == 'build' && runner.os == 'Windows' && runner.arch == 'X64' && steps.cache-python-ssl.outputs.cache-hit != 'true' - name: Config OpenSSL if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | cd "${OPENSSL_SOURCE_PATH}" # --libdir=lib is needed so Python can find OpenSSL libraries # Python doesn't like OpenSSL 4.0 with ASM on Linux arm64 # disable for now if ([ "$RUNNER_OS" == "Linux" ] && [ "$RUNNER_ARCH" == "ARM64" ]); then "${PERL}" ./Configure --libdir=lib --prefix="${OPENSSL_INSTALL_PATH}" no-asm $OPENSSL_CONFIG_OPTS else "${PERL}" ./Configure --libdir=lib --prefix="${OPENSSL_INSTALL_PATH}" $OPENSSL_CONFIG_OPTS fi - name: Rename GNU link on Windows if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' shell: bash run: | mv -v /usr/bin/link /usr/bin/gnulink - name: Make OpenSSL if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | cd "${OPENSSL_SOURCE_PATH}" $MAKE "$MAKEOPT" - name: Install OpenSSL if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | cd "${OPENSSL_SOURCE_PATH}" # install_sw saves us ages processing man pages :-) $MAKE install_sw #if [[ "${RUNNER_OS}" != "Windows" ]]; then # echo "LDFLAGS=-L${OPENSSL_INSTALL_PATH}/lib" >> $GITHUB_ENV #fi #echo "CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1" >> $GITHUB_ENV #case $RUNNER_ARCH in # X64) # echo "CFLAGS=-I${OPENSSL_INSTALL_PATH}/include ${CFLAGS}" >> $GITHUB_ENV # echo "ARCHFLAGS=-arch x86_64" >> $GITHUB_ENV # ;; # ARM64) # echo "CFLAGS=-I${OPENSSL_INSTALL_PATH}/include ${CFLAGS}" >> $GITHUB_ENV # echo "ARCHFLAGS=-arch arm64" >> $GITHUB_ENV # ;; #esac if [[ "${RUNNER_OS}" != "Windows" ]]; then strip "${OPENSSL_INSTALL_PATH}/bin/openssl" fi - name: Run OpenSSL if: matrix.goal == 'build' run: | "${OPENSSL_INSTALL_PATH}/bin/openssl" version -a file "${OPENSSL_INSTALL_PATH}/bin/openssl" - name: Get latest stable Python source if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | cd "${GITHUB_WORKSPACE}/src" git clone https://github.com/python/cpython.git cd "${PYTHON_SOURCE_PATH}" export LATEST_STABLE_TAG=$(git tag --list | grep -v a | grep -v rc | grep -v b | sort -Vr | head -n1) git checkout "${LATEST_STABLE_TAG}" # Temp Python 3.14 patch to work with OpenSSL 4 # Python 3.15 in Oct 2026 should support 4 OOB patch -p1 < "${GITHUB_WORKSPACE}/src/tools/py314-ossl4.diff" export COMPILED_PYTHON_VERSION=${LATEST_STABLE_TAG:1} # Trim the "v" prefix echo "COMPILED_PYTHON_VERSION=${COMPILED_PYTHON_VERSION}" >> $GITHUB_ENV - name: Mac/Linux Configure Python if: matrix.goal == 'build' && runner.os != 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | cd "${PYTHON_SOURCE_PATH}" ./configure --with-openssl="${OPENSSL_INSTALL_PATH}" \ --prefix="${PYTHON_INSTALL_PATH}" \ --enable-shared \ --with-ensurepip=upgrade \ --enable-optimizations \ --with-lto \ --disable-test-modules \ --without-doc-strings || : # exit 0 cat config.log - name: Windows Get External Python deps if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' shell: powershell run: | cd "${env:PYTHON_SOURCE_PATH}" PCBuild\get_externals.bat - name: Windows overwrite external OpenSSL with local if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' shell: powershell run: | cd "${env:PYTHON_SOURCE_PATH}" $env:OPENSSL_EXT_PATH = "$(Get-Item externals\openssl-bin-* | Select -exp FullName)\" echo "External OpenSSL was downloaded to ${env:OPENSSL_EXT_PATH}" Remove-Item -recurse -force "${env:OPENSSL_EXT_PATH}*" # Emulate what this script does: # https://github.com/python/cpython/blob/main/PCbuild/openssl.vcxproj if (${env:RUNNER_ARCH} -eq "X64") { $env:ossl_path = "amd64" } elseif (${env:RUNNER_ARCH} -eq "ARM64") { $env:ossl_path = "arm64" } $env:OPENSSL_EXT_TARGET_PATH = "${env:OPENSSL_EXT_PATH}${env:ossl_path}" echo "Copying our OpenSSL to ${env:OPENSSL_EXT_TARGET_PATH}" mkdir "${env:OPENSSL_EXT_TARGET_PATH}\include\openssl\" Copy-Item -Path "${env:OPENSSL_SOURCE_PATH}\LICENSE.txt" -Destination "${env:OPENSSL_EXT_TARGET_PATH}\LICENSE" cp -v "$env:OPENSSL_INSTALL_PATH\lib\*" "${env:OPENSSL_EXT_TARGET_PATH}" cp -v "$env:OPENSSL_INSTALL_PATH\bin\*" "${env:OPENSSL_EXT_TARGET_PATH}" cp -v "$env:OPENSSL_INSTALL_PATH\include\openssl\*" "${env:OPENSSL_EXT_TARGET_PATH}\include\openssl\" cp -v "$env:OPENSSL_INSTALL_PATH\include\openssl\applink.c" "${env:OPENSSL_EXT_TARGET_PATH}\include\" - name: Windows Install sphinx-build if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' shell: powershell run: | pip install --upgrade pip pip install --upgrade sphinx sphinx-build --version - name: Windows Config/Build/Install Python if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' shell: powershell run: | cd "${env:PYTHON_SOURCE_PATH}" # We need our custom openssl.props which uses OpenSSL 3 DLL names Copy-Item -Path "${env:GITHUB_WORKSPACE}\src\tools\openssl.props" -Destination PCBuild\ -Verbose # We need our custom _hashlib.vcxproj Copy-Item -Path "${env:GITHUB_WORKSPACE}\src\tools\_hashlib.vcxproj" -Destination PCBuild\ -Verbose if (${env:RUNNER_ARCH} -eq "X64") { $env:arch = "x64" #PCBuild\build.bat -c Release -p $env:arch --pgo } elseif (${env:RUNNER_ARCH} -eq "ARM64") { $env:arch = "ARM64" # TODO: figure out why Windows ARM64 isn't compat with PGO optimiazation # causes 10-20% slowdown in Python #PCBuild\build.bat -c Release -p $env:arch } PCBuild\build.bat -c Release -p $env:arch --pgo .\python.bat PC\layout --precompile --preset-default --copy $env:PS_PYTHON_INSTALL_PATH Get-ChildItem -Path $env:PS_PYTHON_INSTALL_PATH -File - name: Mac/Linux Build Python if: matrix.goal == 'build' && runner.os != 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | cd "${PYTHON_SOURCE_PATH}" echo "Running: ${MAKE} ${MAKEOPT}" $MAKE $MAKEOPT - name: Mac/Linux Install Python if: matrix.goal == 'build' && runner.os != 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | cd "${PYTHON_SOURCE_PATH}" $MAKE altinstall $MAKE bininstall strip "${PYTHON_INSTALL_PATH}/bin/python3" export PATH="${PATH}:${PYTHON_INSTALL_PATH}/bin" echo "PATH=${PATH}" >> $GITHUB_ENV echo "PATH: ${PATH}" - name: Run Python run: | "${PYTHON}" -VV "${PYTHON}" -c "import ssl; print(f'Using {ssl.OPENSSL_VERSION}')" - name: Create and use Python .venv run: | cd "$GITHUB_WORKSPACE" curl -o get-pip.py https://bootstrap.pypa.io/get-pip.py "$PYTHON" get-pip.py "$PYTHON" -m venv .venv if [[ "$RUNNER_OS" == "Windows" ]]; then # pyscard seems to build outside venv but not in it. # build it so it's cached. "$PYTHON" -m pip install --upgrade pyscard export PYTHON="${GITHUB_WORKSPACE}/.venv/scripts/python.exe" else export PYTHON="${GITHUB_WORKSPACE}/.venv/bin/python3" fi echo "PYTHON=${PYTHON}" >> $GITHUB_ENV if [[ "$ACTIONS_GOAL" == "test" ]]; then export gam="${PYTHON} gam.py" echo "gam=${gam}" >> $GITHUB_ENV fi #- name: Upgrade pip, wheel, etc # run: | # curl $curl_retry -O https://bootstrap.pypa.io/get-pip.py # "$PYTHON" get-pip.py # "$PYTHON" -m pip install --upgrade pip # "$PYTHON" -m pip install --upgrade wheel # "$PYTHON" -m pip install --upgrade setuptools # "$PYTHON" -m pip install --upgrade importlib-metadata # "$PYTHON" -m pip install --upgrade setuptools-scm # "$PYTHON" -m pip install --upgrade packaging # "$PYTHON" -m pip list - name: Install pip requirements env: GH_TOKEN: ${{ github.token }} run: | if ([ "$RUNNER_OS" == "Windows" ] && [ "$RUNNER_ARCH" == "ARM64" ]); then # custom cryptography wheel for win arm64 since the project doesn't provide one: # https://github.com/pyca/cryptography/issues/14293 gh release download --repo "jay0lee/cryptography-wheels" --pattern "*win_arm64.whl" --clobber "$PYTHON" -m pip install cryptography-*.whl fi "$PYTHON" -m pip install -vvv --upgrade ..[yubikey] - name: Install PyInstaller if: matrix.goal == 'build' run: | # Install latest version of PyInstaller *that's 2 weeks old* # Calculate the exact timestamp for 14 days ago "$PYTHON" -m pip install --upgrade pyinstaller - name: Build GAM with PyInstaller if: matrix.goal != 'test' run: | export distpath="./dist/gam" mkdir -p -v "${distpath}" if [[ "${RUNNER_OS}" == "macOS" ]]; then # Tell our gam.spec to use our code sign certificate export codesign_identity="Jay Lee" # brew OpenSSL gets picked up by PyInstaller # breaking our self-compiled version brew uninstall --ignore-dependencies openssl elif [[ "${RUNNER_OS}" == "Windows" ]]; then # Work around issue where PyInstaller picks up python3.dll from other Python versions # https://github.com/pyinstaller/pyinstaller/issues/7102 export PATH="$(dirname ${PYTHON}):/usr/bin" fi if [[ "$staticx" != "yes" ]]; then export PYINSTALLER_BUILD_ONEDIR=yes fi "${PYTHON}" -m PyInstaller --clean --noconfirm --distpath="${distpath}" gam.spec if [[ "$PYINSTALLER_BUILD_ONEDIR" == "yes" ]]; then mv -v "${distpath}/gam" "${distpath}/gam7" export gampath="${distpath}/gam7" else mv -v "$distpath" "${distpath}7" export gampath="${distpath}7" fi export gampath=$(realpath "$gampath") echo "gampath ${gampath} results:" ls -alRF "$gampath" echo "---- WARNINGS FROM build/gam/warn-gam.txt" cat build/gam/warn-gam.txt echo "---- Analysis FROM build/gam/Analysis-00.toc" cat build/gam/Analysis-00.toc echo "---- EXE data FROM build/gam/EXE-00.toc" cat build/gam/EXE-00.toc export gam="${gampath}/gam" if [[ "${RUNNER_OS}" == "Windows" ]]; then export gam=$(cygpath -w "$gam") echo "GAM on Windows at ${gam}" else export gam=$(realpath "$gam") fi echo "gampath=${gampath}" >> $GITHUB_ENV echo "gam=${gam}" >> $GITHUB_ENV echo -e "GAM: ${gam}\nGAMPATH: ${gampath}" - name: Copy extra package files if: matrix.goal == 'build' run: | cp -v gam/cacerts.pem "$gampath" cp -v LICENSE "$gampath" cp -v GamCommands.txt "$gampath" cp -v GamUpdate.txt "$gampath" if [[ "${RUNNER_OS}" == "Windows" ]]; then cp -v gam-setup.bat "$gampath" fi - name: Install StaticX if: matrix.staticx == 'yes' run: | sudo apt-get -qq --yes update # arm64 needs to build a wheel and needs scons to build sudo apt-get -qq --yes install scons "$PYTHON" -m pip install --upgrade patchelf-wrapper "$PYTHON" -m pip install --upgrade typing_extensions "$PYTHON" -m pip install --upgrade staticx - name: Make StaticX GAM build if: matrix.staticx == 'yes' run: | case $RUNNER_ARCH in X64) ldlib=/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ;; ARM64) ldlib=/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 ;; esac echo "ldlib=${ldlib}" $PYTHON -m staticx -l "${ldlib}" "$gam" "${gam}-staticx" rm -v "$gam" mv -v "${gam}-staticx" "$gam" - name: MacOS send GAM binary for Apple notarization if: runner.os == 'macOS' env: APPLE_KEY: ${{ secrets.APPLE_KEY }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} run: | # Apple wants some kind of "package" submitted so just add gam to a .zip # name it something we can track and link in Apple's notarize process zipfilename="./gam-${RUNNER_ARCH}-${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}.zip" zip -r "$zipfilename" "$gampath" export KEY_FILE="$(mktemp).p8" trap 'rm -f "$KEY_FILE"' EXIT echo "$APPLE_KEY" > "$KEY_FILE" xcrun notarytool submit "$zipfilename" --key "$KEY_FILE" --key-id "$APPLE_KEY_ID" --issuer "$APPLE_ISSUER_ID" rm -v "$KEY_FILE" rm -v "$zipfilename" - name: Basic Tests all jobs id: basictests run: | $gam version extended nooffseterror export GAMVERSION=$($gam version simple) echo "GAM Version ${GAMVERSION}" echo "GAMVERSION=${GAMVERSION}" >> $GITHUB_ENV - name: Install NPM deps if: runner.os == 'Windows' run: | #echo "Installing appium..." #npm install -g appium echo "Installing totp-generator..." npm install totp-generator - name: Install Certum MSI if: runner.os == 'Windows' shell: pwsh run: | #$url = "https://files.certum.eu/software/SimplySignDesktop/Windows/9.4.2.86/SimplySignDesktop-9.4.2.86-64-bit-en.msi" $url = "https://files.certum.eu/software/SimplySignDesktop/Windows/9.4.3.90/SimplySignDesktop-9.4.3.90-64-bit-en.msi" $file = "SimplySignDesktop.msi" Invoke-WebRequest $url -OutFile $file $log = "install.log" $procMain = Start-Process "msiexec" "/i `"$file`" /qn /l*! `"$log`"" -NoNewWindow -PassThru $procLog = Start-Process "powershell" "Get-Content -Path `"$log`" -Wait" -NoNewWindow -PassThru $procMain.WaitForExit() $procLog.Kill() - name: Run SSD directly if: runner.os == 'Windows' shell: pwsh run: | Write-Host "Running SSD..." & "C:\\Program Files\\Certum\\SimplySign Desktop\\SimplySignDesktop.exe" Start-Sleep -Seconds 10 & "C:\\Program Files\\Certum\\SimplySign Desktop\\SimplySignDesktop.exe" - name: Login to Certum if: runner.os == 'Windows' shell: pwsh env: TOTP_SECRET: ${{ secrets.TOTP_SECRET }} run: | write-host "running SimplySignDesktop login..." node tools/ssd.mjs --log-level warn Get-ChildItem -Path $env:GITHUB_WORKSPACE write-host "sleeping during login..." Start-Sleep 10 - name: Archive artifacts uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0 if: runner.os == 'Windows' with: archive: true name: images-${{ matrix.os }} if-no-files-found: ignore path: | ${{ github.workspace }}/*.png ${{ github.workspace }}/*.log - name: Sign gam.exe if: runner.os == 'Windows' shell: pwsh run: | write-Host "Signing ${env:gam}...." # Always explicitely use x64 version os signtool.exe, arm64 version apparently can't # see Certum certs since SimplySignDesktop is x64-only today. Start-Process -Wait -NoNewWindow -ErrorAction Continue -FilePath 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' -ArgumentList "sign", "/sha1", "$env:WINDOWS_CODESIGN_CERT_HASH", "/tr", "http://time.certum.pl", "/td", "SHA256", "/fd", "SHA256", "/v", "$env:gam" write-Host "Verifying signature of ${env:gam}...." # verify signature. If we failed to sign we should fail to verify and die. & 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' verify /pa /v "$env:gam" - name: Configure user and service account auth id: configserviceaccount env: oa2: ${{ secrets[format('GAM_GHA_{0}', matrix.jid)] }} run: | ../.github/actions/decrypt.sh "${GAMCFGDIR}" $gam create signjwtserviceaccount - name: Attest gam executable was generated from this Action uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 if: matrix.goal == 'build' with: subject-path: ${{ env.gam }} - name: Linux/MacOS package if: runner.os != 'Windows' && matrix.goal == 'build' run: | if [[ "${RUNNER_OS}" == "macOS" ]]; then GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-macos${MACOSX_DEPLOYMENT_TARGET}-${arch}.tar.xz" elif [[ "${RUNNER_OS}" == "Linux" ]]; then if [[ "${staticx}" == "yes" ]]; then libver="legacy" else libver="glibc$(ldd --version | awk '/ldd/{print $NF}')" fi GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-linux-${arch}-${libver}.tar.xz" fi echo "GAM Archive ${GAM_ARCHIVE}" tar -C "${gampath}/.." --create --verbose --exclude-from "${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" --file $GAM_ARCHIVE --xz gam7 - name: Windows package zip if: runner.os == 'Windows' && matrix.goal != 'test' run: | echo "started in $(pwd)" cd "${gampath}/.." echo "moved to $(pwd)" GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-windows-${arch}.zip" /c/Program\ Files/7-Zip/7z.exe a -tzip "$GAM_ARCHIVE" gam7 "-xr@${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" -bb3 - name: Windows package exe with Inno Setup if: runner.os == 'Windows' && matrix.goal != 'test' run: | choco install innosetup export signtool="C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe" iscc \ /S"gamsigntool=$signtool sign /sha1 $WINDOWS_CODESIGN_CERT_HASH /tr http://time.certum.pl /td SHA256 /fd SHA256 /v \$f" \ /O"$GITHUB_WORKSPACE" \ gam.iss - name: Attest that gam package files were generated from this Action uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.goal == 'build' with: subject-path: | gam*.tar.xz gam*.zip gam*.exe # gam*.msi - name: Archive tar.xz artifacts uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0 if: runner.os != 'Windows' with: archive: false if-no-files-found: ignore path: | gam*.tar.xz - name: Archive zip artifacts uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0 if: runner.os == 'Windows' with: archive: false if-no-files-found: ignore path: | gam*.zip - name: Archive exe artifacts uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0 if: runner.os == 'Windows' with: archive: false if-no-files-found: ignore path: | gam*.exe - name: Basic Tests build jobs only if: matrix.goal != 'test' && steps.cache-python-ssl.outputs.cache-hit != 'true' run: | export voutput=$($gam version extended nooffseterror) export python_line=$(echo -e "${voutput}" | grep "Python ") export python_arr=($python_line) export this_python=${python_arr[1]} if [[ "${this_python}" != "${COMPILED_PYTHON_VERSION}" ]]; then echo "ERROR: Tried to compile Python ${COMPILED_PYTHON_VERSION} but ended up with ${this_python}" exit 1 fi export openssl_line=$(echo -e "${voutput}" | grep "OpenSSL ") export openssl_arr=($openssl_line) export this_openssl="${openssl_arr[1]}" if [[ "${this_openssl}" != "${COMPILED_OPENSSL_VERSION}" ]]; then echo "ERROR: Tried to compile OpenSSL ${COMPILED_OPENSSL_VERSION} but ended up with ${this_openssl}" exit 1 fi echo "We successfully compiled Python ${this_python} and OpenSSL ${this_openssl}" - name: Live API tests if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') run: | run_gam() { local allowed_codes="0" if [[ "$1" == "-a" ]]; then allowed_codes="$2" shift 2 fi echo "::group::Executing: gam $*" local exit_code=0 $gam "$@" || exit_code=$? echo "::endgroup::" allowed_codes="${allowed_codes//,/ }" local passed=false for code in $allowed_codes; do if [ "$exit_code" -eq "$code" ]; then passed=true break fi done if [ "$passed" = true ]; then echo "| \`gam $*\` | 🟢 Pass | $exit_code |" >> $GITHUB_STEP_SUMMARY return 0 # Mask the allowed non-zero exit code so GHA continues else echo "| \`gam $*\` | 🔴 Fail | $exit_code |" >> $GITHUB_STEP_SUMMARY exit $exit_code # Hard fail the step for unapproved errors fi } export gam_user="gam-gha-${JID}@pdl.jaylee.us" echo "gam_user=${gam_user}" >> $GITHUB_ENV run_gam config customer_id "C03uzfv2s" save run_gam config domain "pdl.jaylee.us" save run_gam config admin_email "${gam_user}" save run_gam config enable_dasa false save run_gam oauth info run_gam oauth refresh run_gam config enable_dasa true save run_gam checkconn run_gam user "$gam_user" check serviceaccount run_gam info domain run_gam info user export tstamp=$($PYTHON -c "import time; print(time.time_ns())") export newbase="gha_test_${JID}_${tstamp}" export newuser="${newbase}@pdl.jaylee.us" export newgroup="${newbase}-group@pdl.jaylee.us" export newalias="${newbase}-alias@pdl.jaylee.us" export newbuilding="${newbase}-building" export newresource="${newbase}-resource" export newou="aaaGithub Actions/${newbase}" echo "### GAM Execution Report" >> $GITHUB_STEP_SUMMARY echo "| Command | Status |" >> $GITHUB_STEP_SUMMARY echo "| :--- | :---: |" >> $GITHUB_STEP_SUMMARY # cleanup old runs run_gam config enable_dasa false save run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./vh.csv print vaultholds run_gam -a "0 55" csv ./vh.csv gam delete vaulthold "id:~~holdId~~" matter "id:~~matterId~~" run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./vm-open.csv print vaultmatters matterstate OPEN run_gam csv ./vm-open.csv gam update vaultmatter "id:~~matterId~~" action close run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./vm-closed.csv print vaultmatters matterstate CLOSED run_gam csv ./vm-closed.csv gam update vaultmatter "id:~~matterId~~" action delete run_gam config csv_output_row_filter "Emails.1.address:regex:^gha_test-${JID}_" redirect csv ./contacts.csv print contacts run_gam csv ./contacts.csv gam delete contact ~ContactID run_gam config enable_dasa true save run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./features.csv print features run_gam csv ./features.csv gam delete feature ~name run_gam config csv_output_row_filter "name:regex:^gha_test_${JID}_" redirect csv ./sd.csv user $gam_user print shareddrives asadmin run_gam csv ./sd.csv gam user $gam_user delete shareddrive ~id nukefromorbit run_gam redirect csv ./users.csv print users query "gha.jid=$JID" run_gam csv ./users.csv gam delete user ~primaryEmail run_gam config csv_output_row_filter "name:regex:^gha_test_${JID}_" redirect csv ./ous.csv print ous fromparent "aaaGithub Actions" run_gam csv ./ous.csv gam delete ou ~orgUnitId run_gam config csv_output_row_filter "email:regex:^gha_test_${JID}_" redirect csv ./cigroups.csv print cigroups run_gam csv ./cigroups.csv gam delete cigroup ~email run_gam config csv_output_row_filter "resourceId:regex:^gha_test_${JID}_" redirect csv ./resources.csv print resources run_gam csv ./resources.csv gam delete resource ~resourceId run_gam config csv_output_row_filter "buildingId:regex:^gha_test_${JID}_" redirect csv ./buildings.csv print buildings run_gam csv ./buildings.csv gam delete building ~buildingId run_gam config csv_output_row_filter "displayName:regex:^El\ Goog\ gha_test_${JID}_" redirect csv ./ssoprofiles.csv print inboundssoprofiles run_gam csv ./ssoprofiles.csv gam delete inboundssoprofile "id:~~name~~" echo "Creating OrgUnit ${newou}" run_gam create ou "${newou}" export GAM_THREADS=5 echo email > sample.csv; for i in {1..10}; do echo "${newbase}-bulkuser-$i" >> sample.csv; done driveid=$($gam user $gam_user add shareddrive "${newbase}" returnidonly) echo "Created shared drive ${driveid}" run_gam create user $newuser firstname GHA lastname $JID displayname "Github Actions ${JID}" password uniquerandom recoveryphone 12125121110 recoveryemail jay0lee@gmail.com gha.jid $JID languages en+,en-GB- ou "$newou" run_gam user $newuser update photo https://dummyimage.com/98x98/000/fff.jpg run_gam user $newuser get photo run_gam user $newuser delete photo run_gam create alias $newalias user $newuser run_gam create group $newgroup name "GHA $JID group" description "This is a description" isarchived true run_gam user $gam_user sendemail recipient dev-null@pdl.jaylee.us subject "test message $newbase" message "GHA test message" run_gam user $newuser add license workspaceenterpriseplus run_gam update user $newuser ou root # GAM synonym for / root OU run_gam update user $newuser ou "$newou" run_gam config enable_dasa false save # don't expose policy output run_gam show policies > policies.csv run_gam create contact firstname GHA lastname "$JID" email work "${newbase}@example.com" primary run_gam print contacts run_gam print privileges run_gam config enable_dasa true save run_gam update cigroup $newgroup security memberrestriction 'member.type == 1 || member.customer_id == groupCustomerId()' run_gam info cigroup $newgroup run_gam update group $newgroup add owner $gam_user run_gam update group $newgroup add member $newuser run_gam config enable_dasa false save # 9/17/24 temp disable due to Google API sluggishness to see new users for admin commands # run_gam create admin $newuser _GROUPS_EDITOR_ROLE CUSTOMER # condition nonsecuritygroup # 9/13/25 temp disable due to hangs # run_gam create admin $newgroup _HELP_DESK_ADMIN_ROLE org_unit "${newou}" # run_gam config csv_output_row_filter "assignedToUser:regex:${newuser}" print admins | run_gam csv - gam delete admin "~roleAssignmentId" # run_gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | run_gam csv - gam delete admin "~roleAssignmentId" run_gam config enable_dasa false save run_gam csv sample.csv gam create user ~~email~~ firstname "GHA Bulk" lastname ~~email~~ gha.jid $JID ou "${newou}" run_gam csv sample.csv gam update user ~~email~~ recoveryphone 12125121110 recoveryemail jay0lee@gmail.com password random displayname "GitHub Actions Bulk ${JID}" run_gam csv sample.csv gam update user ~~email~~ recoveryphone "" recoveryemail "" run_gam config enable_dasa false save run_gam csv sample.csv gam user ~email add license workspaceenterpriseplus #run_gam user $newuser add contactdelegate "${newbase}-bulkuser-1" #run_gam user $newuser print contactdelegates run_gam config enable_dasa true save run_gam csv sample.csv gam user $gam_user sendemail recipient ~~email~~@pdl.jaylee.us subject "test message $newbase" message "GHA test message" run_gam csv sample.csv gam update group $newgroup add member ~email run_gam info group $newgroup run_gam info cigroup $newgroup membertree # confirm mailbox is provisoned before continuing run_gam user $newuser waitformailbox retries 50 run_gam user $newuser imap on run_gam user $newuser show imap run_gam user $newuser show delegates export biohazard=$(echo -e '\xe2\x98\xa3') run_gam user $newuser label "$biohazard unicode biohazard $biohazard" run_gam user $newuser show labels run_gam user $newuser show labels > labels.txt run_gam user $gam_user importemail subject "GHA import $newbase" message "This is a test import" labels IMPORTANT,UNREAD,INBOX,STARRED run_gam user $gam_user insertemail subject "GHA insert $newbase" file gam.py labels INBOX,UNREAD # yep body is gam code run_gam user $gam_user sendemail recipient admin@pdl.jaylee.us subject "GHA send $gam_user $newbase" file gam.py run_gam user $gam_user draftemail subject "GHA draft $newbase" message "Draft message test" run_gam csvfile sample.csv:email waitformailbox retries 20 run_gam user $newuser delegate to "${newbase}-bulkuser-1" || if [ $? != 50 ]; then exit $?; fi # expect a 50 return code (delegation failed) run_gam -a "0 60" users "$gam_user $newbase-bulkuser-1 $newbase-bulkuser-2 $newbase-bulkuser-3" delete messages query in:anywhere maxtodelete 99999 doit run_gam -a "0 60" users "$newbase-bulkuser-4 $newbase-bulkuser-5 $newbase-bulkuser-6" trash messages query in:anywhere maxtotrash 99999 doit run_gam -a "0 60" users "$newbase-bulkuser-7 $newbase-bulkuser-8 $newbase-bulkuser-9" modify messages query in:anywhere maxtomodify 99999 addlabel IMPORTANT addlabel STARRED doit run_gam user $newuser delete label --ALL_LABELS-- run_gam config csv_output_row_filter "name:regex:gha-test-${JID}" redirect csv ./features.csv print features run_gam csv ./features.csv gam delete feature ~name run_gam create feature name VC-$newbase run_gam create feature name Whiteboard-$newbase run_gam create building "My Building - $newbase" id $newbuilding floors 1,2,3,4,5,6,7,8,9,10,11,12,14,15 description "No 13th floor here..." run_gam create resource $newresource "Resource Calendar $tstamp" capacity 25 features Whiteboard-$newbase,VC-$newbase building $newbuilding floor 15 type Room run_gam info resource $newresource run_gam user $newuser add drivefile drivefilename "TPS Reports" mimetype gfolder run_gam user $newuser show filelist run_gam redirect csv ./cal-acl.csv calendar $gam_user printacl run_gam csv ./cal-acl.csv gam calendar $gam_user delete ~id # clear ACLs run_gam calendar $gam_user add read domain run_gam calendar $gam_user add freebusy default run_gam calendar $gam_user add editor $newuser run_gam calendar $gam_user showacl run_gam redirect csv ./cal-acl.csv calendar $gam_user printacl run_gam csv ./cal-acl.csv gam calendar $gam_user delete ~id run_gam calendar $gam_user addevent summary "GHA test event" start +1h end +2h attendee $newgroup hangoutsmeet guestscanmodify true sendupdates all run_gam calendar $gam_user printevents after -0d run_gam config enable_dasa false save matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly) run_gam create vaulthold matter "$matterid" name "GHA hold ${newbase}" corpus mail ou "$newou" run_gam print vaultmatters matterstate open run_gam print vaultholds matter $matterid run_gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser run_gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail ou "$newou" run_gam redirect csv ./exports.csv print exports matter $matterid run_gam csv ./exports.csv gam info export $matterid id:~~id~~ run_gam config enable_dasa true save run_gam csv sample.csv gam user ~email add calendar id:$newresource run_gam delete resource $newresource run_gam delete feature Whiteboard-$newbase run_gam delete feature VC-$newbase run_gam delete building $newbuilding run_gam delete group $newgroup run_gam config enable_dasa false save echo start run_gam user $newuser delete license workspaceenterpriseplus echo finish run_gam config enable_dasa true save run_gam -a "0 20" whatis $newuser run_gam user $gam_user show tokens run_gam config enable_dasa false save download_dir="${RUNNER_TEMP}/TEMP_DELETE_ME" mkdir -v "$download_dir" run_gam redirect csv ./exports.csv print exports matter $matterid run_gam csv ./exports.csv gam download export $matterid id:~~id~~ targetfolder "$download_dir" rm -rvf "$download_dir" run_gam delete hold "GHA hold $newbase" matter $matterid run_gam update matter $matterid action close run_gam update matter $matterid action delete # shakes off vault hold on user so we can delete run_gam redirect csv ./users.csv print users query "email:${newuser}" orgunitpath run_gam csv ./users.csv gam update user ~primaryEmail ou ~orgUnitPath run_gam user $newuser show holds || if [ $? != 55 ]; then exit $?; fi # expect a 55 return code export sn="$JID$JID$JID$JID-$(openssl rand -base64 32 | sed 's/[^a-zA-Z0-9]//g')" run_gam create device serialnumber $sn devicetype android run_gam delete contacts emailmatchpattern "^${newbase}@example.com$" run_gam config enable_dasa true save run_gam redirect csv ./users.csv print users query "gha.jid=$JID" run_gam -a "0 50" csv ./users.csv gam delete user ~primaryEmail run_gam print mobile run_gam print devices clientstates run_gam print browsers run_gam print cros allfields orderby serialnumber run_gam show crostelemetry storagepercentonly run_gam report usageparameters customer run_gam report usage customer parameters gmail:num_emails_sent,accounts:num_1day_logins run_gam report customer todrive tdnobrowser #run_gam report users fields accounts:is_less_secure_apps_access_allowed,gmail:last_imap_time,gmail:last_pop_time filters "accounts:last_login_time>2025-01-01T00:00:00.000Z" todrive tdnobrowser run_gam report users todrive tdnobrowser run_gam report admin start -3d todrive tdnobrowser run_gam redirect csv ./devices.csv print devices nopersonaldevices nodeviceusers filter "serial:$JID$JID$JID$JID-" run_gam csv ./devices.csv gam delete device id ~name run_gam config enable_dasa false save run_gam print userinvitations run_gam redirect csv ./invitations.csv print userinvitations run_gam csv ./invitations.csv gam send userinvitation ~name run_gam config enable_dasa false save run_gam create caalevel "zzz_${newbase}" basic condition ipsubnetworks 1.1.1.1/32,2.2.2.2/32 endcondition run_gam print caalevels run_gam delete caalevel "zzz_${newbase}" run_gam user $gam_user add drivefile localfile gam.py parentid "${driveid}" run_gam user $gam_user update shareddrive "${driveid}" ou "${newou}" run_gam user $gam_user show shareddrives asadmin run_gam user $gam_user update shareddrive "${driveid}" ou "aaaGithub Actions" # so we can delete our OU... run_gam user $gam_user delete shareddrive "${driveid}" nukefromorbit ssoprofile=$(run_gam config debug_level 1 create inboundssoprofile name "El Goog ${newbase}" loginurl https://www.google.com logouturl https://www.google.com changepasswordurl https://www.google.com entityid ElGoog return_name_only) if [ ${ssoprofile} != 'inProgress' ]; then run_gam create inboundssocredential profile "id:${ssoprofile}" generate_key #run_gam create inboundssoassignment profile "id:${ssoprofile}" orgunit "${newou}" mode SAML_SSO #run_gam delete inboundssoassignment "orgunit:${newou}" run_gam delete inboundssoprofile "id:${ssoprofile}" fi echo "printer model count:" run_gam print printermodels | wc -l run_gam print printers printerid=$($gam create printer displayname "${newbase}" uri ipp://localhost:631 driverless description "made by ${gam_user}" ou "${newou}" returnIdOnly) run_gam info printer "$printerid" run_gam delete printer "$printerid" run_gam delete ou "${newou}" - name: Tar Cache archive if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true' working-directory: ${{ github.workspace }} run: | #if [[ "${RUNNER_OS}" == "Windows" ]]; then # tar_folders="src/cpython/ bin/ssl" #else # tar_folders="bin/" #fi tar_folders="bin/" echo '.git*' > ./excludes.txt tar cJvvf cache.tar.xz --exclude-from=excludes.txt $tar_folders publish: if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') runs-on: ubuntu-24.04 needs: build permissions: contents: write packages: write pull-requests: read steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false fetch-depth: 0 - name: Download artifacts uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: path: gam-binaries/ merge-multiple: true skip-decompress: true - name: VirusTotal Scan uses: crazy-max/ghaction-virustotal@d34968c958ae283fe976efed637081b9f9dcf74f # 4.2.0 with: vt_api_key: ${{ secrets.VT_API_KEY }} files: | gam-binaries/* - name: Set datetime version string id: dateversion run: | export dateversion="$(date +'%Y%m%d.%H%M%S')" echo "Date version: ${dateversion}" echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT - name: Publish draft release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: draft: true prerelease: false tag_name: "${{ steps.dateversion.outputs.dateversion }}" fail_on_unmatched_files: true files: | gam-binaries/*