# Limitations of GitHub Actions:
# Fedora: https://github.com/actions/runner-images/issues/10802
# on.pull_request.paths: https://github.com/actions/runner/issues/2324
# jobs.<job_id>.continue-on-error: https://github.com/orgs/community/discussions/15452
# etc: https://fusectore.dev/2022/09/25/github-actions-pitfalls.html
name: Portability Testing
on:
  push:
    paths:
      - '!**'
      - '.github/workflows/test.yml'
      - 'updater.sh'
      - 'prefsCleaner.sh'
jobs:
  sh:
    defaults:
      run:
        shell: sh {0}
    strategy:
      fail-fast: false
      matrix:
        script: [ updater.sh, prefsCleaner.sh ]
        shell: [ bash, busybox, dash, ksh, mksh, posh, yash, zsh ]
        os: [ ubuntu-latest ]
        include:
          - script: updater.sh
            shell: bash
            os: macos-latest
          - script: prefsCleaner.sh
            shell: bash
            os: macos-latest
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - name: Install POSIX compliant shell from the Ubuntu repositories
        if: ${{ startsWith(matrix.os, 'ubuntu-') }}
        timeout-minutes: 5
        run: |
          sudo apt update -y &&
            sudo apt install -y ${{ matrix.shell }} ||
            exit
      - name: Point `/bin/sh` at the newly installed shell
        if: ${{ runner.os == 'Linux' }}
        run: sudo ln -sf /usr/bin/${{ matrix.shell }} /bin/sh || exit
      - name: Test dot sourcing and obtain exit status definitions
        timeout-minutes: 1
        run: |
          case ${{ matrix.shell }} in
            busybox)
              shell='busybox ash'
              ;;
            *)
              shell=${{ matrix.shell }}
              ;;
          esac &&
            eval "$shell" <<'EOF'
          case ${{ matrix.shell }} in
            zsh)
              emulate sh
              ;;
          esac
          . ./${{ matrix.script }}
          [ "$?" -eq "$_EX_OK" ] ||
            echo '::error file=${{ matrix.script }}::Dot sourcing failed'
          exit_status_definitions | tr -d ' ' >>"$GITHUB_ENV"
          EOF
          [ "$?" -eq 0 ] || exit
      - name: Test the `-h` option
        timeout-minutes: 1
        run: ./${{ matrix.script }} -h
      - name: Test passing an unsupported option to the script
        timeout-minutes: 1
        run: |
          ./${{ matrix.script }} -9
          [ "$?" -eq "$_EX_USAGE" ]
      - name: Test nonexistent profiles.ini
        timeout-minutes: 1
        run: |
          (HOME=/nosuchdir ./${{ matrix.script }} -sl)
          [ "$?" -eq "$_EX_NOINPUT" ]
      - name: Test profile directory missing write or search permissions
        timeout-minutes: 1
        run: |
          unwritable_dir=$(mktemp -d) &&
            chmod a-w "$unwritable_dir" &&
            ./${{ matrix.script }} -sp "$unwritable_dir"
          unwritable_status=$?
          unsearchable_dir=$(mktemp -d) &&
            chmod a-x "$unsearchable_dir" &&
            ./${{ matrix.script }} -sp "$unsearchable_dir"
          unsearchable_status=$?
          [ "$unwritable_status" -eq "$_EX_UNAVAILABLE" ] &&
            {
              [ "$unsearchable_status" -eq "$_EX_UNAVAILABLE" ] ||
              [ "$unsearchable_status" -eq "$_EX_FAIL" ] # readlinkf failed.
            }
      - name: Test running as root
        timeout-minutes: 1
        run: |
          sudo ./${{ matrix.script }}
          [ "$?" -eq "$_EX_USAGE" ]
      - name: Test profile directory containing certain root owned files
        if: ${{ matrix.script == 'updater.sh' }}
        timeout-minutes: 1
        run: |
          temp_dir=$(mktemp -d) &&
            sudo touch "$temp_dir/user.js" &&
            ./${{ matrix.script }} -p "$temp_dir"
          [ "$?" -eq "$_EX_CONFIG" ]
      - name: Test noninteractive run
        timeout-minutes: 3
        run: |
          temp_dir=$(mktemp -d) &&
            cp ./${{ matrix.script }} ./user.js "$temp_dir" && (
              cd "$temp_dir" &&
              ln -s 127.0.0.2:999 .parentlock &&
              ln -s 127.0.0.2:999 lock &&
              echo 'user_pref("app.installation.timestamp", "0");' >prefs.js &&
              # yes | tr -d '\n' | ./${{ matrix.script }} -ds hangs on macOS.
              printf '%s' 'yyyyyyyyy' | ./${{ matrix.script }} -ds
            )