diff --git a/.github/workflows/manual_test.yaml b/.github/workflows/manual_test.yaml new file mode 100644 index 0000000..56822db --- /dev/null +++ b/.github/workflows/manual_test.yaml @@ -0,0 +1,111 @@ +name: Manual Test + +on: + workflow_dispatch: + inputs: + password: + type: string + description: 'Password for the test SSH account (webssh_tester). Leave blank to auto-generate a random password.' + required: false + default: '' + duration: + type: string + description: 'How long to keep the test environment running, in minutes (max 60)' + required: false + default: '30' + +jobs: + manual-test: + name: Manual Test Environment + runs-on: ubuntu-latest + permissions: + contents: read + timeout-minutes: 65 + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: 'true' + fetch-depth: 0 + + - name: Set up SSH server and test account + id: setup + shell: bash + env: + TEST_PASS_INPUT: ${{ inputs.password }} + run: | + sudo apt-get update + sudo apt-get install -y openssh-server + # Enable password authentication + sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config + sudo systemctl start ssh + # Use the provided password or auto-generate one + TEST_USER=webssh_tester + if [ -n "$TEST_PASS_INPUT" ]; then + TEST_PASS="$TEST_PASS_INPUT" + else + TEST_PASS=$(openssl rand -hex 10) + fi + sudo useradd -m -s /bin/bash "$TEST_USER" + echo "$TEST_USER:$TEST_PASS" | sudo chpasswd + echo "test_user=$TEST_USER" >> "$GITHUB_OUTPUT" + echo "test_pass=$TEST_PASS" >> "$GITHUB_OUTPUT" + + - name: Configure and build + shell: bash + run: | + cmake -Bbuild -DCMAKE_BUILD_TYPE=Release + cmake --build build --target webssh_cpp -j4 + + - name: Start webssh_cpp + shell: bash + run: | + ./build/src/webssh_cpp -p 8080 & + sleep 2 + echo "webssh_cpp started on port 8080" + + - name: Print test environment info + shell: bash + run: | + echo "============================================" + echo " WebSSH Manual Test Environment" + echo "============================================" + echo "" + echo " webssh_cpp is running on port 8080 of this runner." + echo " Connect to the tmate session shown below, then" + echo " forward port 8080 to your local machine:" + echo " ssh -L 8080:localhost:8080 " + echo " Then open http://localhost:8080/ in your browser." + echo "" + echo " SSH credentials to enter in the web terminal:" + echo " Host : 127.0.0.1" + echo " Port : 22" + echo " Username : ${{ steps.setup.outputs.test_user }}" + echo " Password : ${{ steps.setup.outputs.test_pass }}" + echo "" + echo " Environment will stay up for ${{ inputs.duration }} minutes (max 60)." + echo " Cancel this workflow run to shut it down early." + echo "============================================" + + - name: Set up tmate session + uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: true + detached: true + + - name: Wait for manual testing + shell: bash + run: | + DURATION_INPUT="${{ inputs.duration }}" + # Validate that the input is a positive integer; fall back to 30 if not. + if ! [[ "$DURATION_INPUT" =~ ^[0-9]+$ ]] || [ "$DURATION_INPUT" -le 0 ]; then + DURATION_INPUT=30 + fi + # Cap at 60 minutes to avoid excessive runner usage. + if [ "$DURATION_INPUT" -gt 60 ]; then + DURATION_INPUT=60 + fi + DURATION_SECONDS=$(( DURATION_INPUT * 60 )) + echo "Keeping environment alive for ${DURATION_INPUT} minute(s)..." + sleep "$DURATION_SECONDS" diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..713f741 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,84 @@ +name: Test + +on: + workflow_dispatch: + +jobs: + test: + name: ${{ matrix.os }} - test + runs-on: ${{ matrix.os }} + permissions: + contents: read + timeout-minutes: 60 + strategy: + matrix: + os: [ubuntu-22.04, ubuntu-latest, windows-latest] + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: 'true' + fetch-depth: 0 + + - name: Set up SSH server for integration tests (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y openssh-server + # Enable password authentication + sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config + sudo systemctl start ssh + # Create a temporary test user with a random password + TEST_USER=webssh_testuser + TEST_PASS=$(openssl rand -hex 8) + sudo useradd -m -s /bin/bash "$TEST_USER" + echo "$TEST_USER:$TEST_PASS" | sudo chpasswd + # Export credentials for subsequent steps + echo "TEST_SSH_HOST=127.0.0.1" >> "$GITHUB_ENV" + echo "TEST_SSH_PORT=22" >> "$GITHUB_ENV" + echo "TEST_SSH_USER=$TEST_USER" >> "$GITHUB_ENV" + echo "TEST_SSH_PASS=$TEST_PASS" >> "$GITHUB_ENV" + + - name: Set up SSH server for integration tests (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + # Install and start the built-in OpenSSH server + Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 + Start-Service sshd + # Create a temporary test user with a cryptographically random password + $TestUser = "webssh_testuser" + $bytes = [byte[]]::new(8) + [System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes) + $TestPass = [System.Convert]::ToHexString($bytes).ToLower() + $SecPass = ConvertTo-SecureString $TestPass -AsPlainText -Force + New-LocalUser $TestUser -Password $SecPass -PasswordNeverExpires + # Export credentials for subsequent steps + "TEST_SSH_HOST=127.0.0.1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "TEST_SSH_PORT=22" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "TEST_SSH_USER=$TestUser" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + "TEST_SSH_PASS=$TestPass" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + - name: Set reusable strings + id: strings + shell: bash + run: | + unix_workspace_path=$(echo "${{ github.workspace }}" | sed 's/\\/\//g') + echo "build-output-dir=${unix_workspace_path}/build" >> "$GITHUB_OUTPUT" + + - name: Configure + shell: bash + run: | + cmake -B${{ steps.strings.outputs.build-output-dir }} -DCMAKE_BUILD_TYPE=Debug + + - name: Build tests + shell: bash + run: | + cmake --build ${{ steps.strings.outputs.build-output-dir }} --target webssh_cpp_tests -j4 + + - name: Run tests + shell: bash + run: | + ctest --test-dir ${{ steps.strings.outputs.build-output-dir }} --output-on-failure