Repository navigation
Conversation
Agent-Logs-Url: https://github.com/ohto-ai/webssh_cpp/sessions/a4b80580-46e6-4c54-a50e-31fb0e45fd9c Co-authored-by: ohto-ai <46275725+ohto-ai@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds GitHub Actions workflows to run the project’s test suite in CI (including SSH integration tests) and to spin up an on-demand manual testing environment for the running webssh_cpp app.
Changes:
- Added
test.yamlto build and executewebssh_cpp_testson Ubuntu runners, provisioning a local SSH server/user for integration tests. - Added
manual_test.yaml(workflow_dispatch) to build and runwebssh_cpp, then expose it via a public tunnel for human testing for a configurable duration.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| .github/workflows/test.yaml | New CI workflow to provision local SSH and run ctest for webssh_cpp_tests on Ubuntu matrix. |
| .github/workflows/manual_test.yaml | New manually triggered workflow to run webssh_cpp and expose it over a public tunnel for interactive testing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| push: | ||
| paths: | ||
| - '.github/workflows/test.yaml' | ||
| - 'src/**' | ||
| - 'inc/**' | ||
| - 'test/**' | ||
| - 'CMakeLists.txt' | ||
| - '*.cmake' | ||
| pull_request: | ||
| paths: | ||
| - '.github/workflows/test.yaml' | ||
| - 'src/**' | ||
| - 'inc/**' | ||
| - 'test/**' | ||
| - 'CMakeLists.txt' | ||
| - '*.cmake' |
There was a problem hiding this comment.
This workflow overlaps with the existing .github/workflows/ci.yaml triggers (same push/PR path filters) and OS matrix, so pushes/PRs will run two near-identical CI jobs and increase total CI time. Consider consolidating by re-enabling/adding the test step in ci.yaml instead of introducing a separate workflow, or adjusting triggers so only one of them runs for a given change set.
| push: | |
| paths: | |
| - '.github/workflows/test.yaml' | |
| - 'src/**' | |
| - 'inc/**' | |
| - 'test/**' | |
| - 'CMakeLists.txt' | |
| - '*.cmake' | |
| pull_request: | |
| paths: | |
| - '.github/workflows/test.yaml' | |
| - 'src/**' | |
| - 'inc/**' | |
| - 'test/**' | |
| - 'CMakeLists.txt' | |
| - '*.cmake' | |
| workflow_dispatch: |
|
|
||
| - name: Set up SSH server for integration tests | ||
| shell: bash | ||
| run: | |
There was a problem hiding this comment.
apt-get install is run without an apt-get update, which can intermittently fail on GitHub-hosted runners when package indexes are stale. Adding an update step (or using apt-get update immediately before install) will make the workflow more reliable.
| run: | | |
| run: | | |
| sudo apt-get update |
| sudo systemctl start ssh | ||
| # Create a temporary test user with a random password | ||
| TEST_USER=webssh_testuser | ||
| TEST_PASS=$(openssl rand -base64 12 | tr -dc 'A-Za-z0-9' | head -c 16) |
There was a problem hiding this comment.
Password generation can produce fewer than 16 characters after the tr -dc filter (or even an empty string), which would make SSH auth flaky. Use a generation method that guarantees length/charset (e.g., openssl rand -hex ... or loop until the desired length is reached).
| TEST_PASS=$(openssl rand -base64 12 | tr -dc 'A-Za-z0-9' | head -c 16) | |
| TEST_PASS=$(openssl rand -hex 8) |
| - name: Set up SSH server and test account | ||
| id: setup | ||
| shell: bash | ||
| run: | |
There was a problem hiding this comment.
apt-get install is run without an apt-get update, which can intermittently fail on GitHub-hosted runners when package indexes are stale. Adding an update step (or using apt-get update immediately before install) will make the workflow more reliable.
| run: | | |
| run: | | |
| sudo apt-get update |
| - name: Set up public tunnel | ||
| shell: bash | ||
| run: | | ||
| # Start a reverse SSH tunnel via localhost.run (no account required) | ||
| ssh -o StrictHostKeyChecking=no \ | ||
| -o ServerAliveInterval=30 \ | ||
| -o ServerAliveCountMax=10 \ | ||
| -R 80:localhost:8080 \ | ||
| nokey@localhost.run 2>&1 | tee /tmp/tunnel.log & | ||
| echo "TUNNEL_PID=$!" >> "$GITHUB_ENV" | ||
| # Wait for the tunnel URL to appear in the log | ||
| for i in $(seq 1 15); do | ||
| TUNNEL_URL=$(grep -oP 'https?://[^\s]+' /tmp/tunnel.log | head -1) | ||
| if [ -n "$TUNNEL_URL" ]; then | ||
| break | ||
| fi | ||
| sleep 2 | ||
| done | ||
| echo "TUNNEL_URL=${TUNNEL_URL:-http://localhost:8080 (tunnel unavailable)}" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Print test environment info | ||
| shell: bash | ||
| run: | | ||
| echo "============================================" | ||
| echo " WebSSH Manual Test Environment" | ||
| echo "============================================" | ||
| echo "" | ||
| echo " 1. Open the web interface in your browser:" | ||
| echo " $TUNNEL_URL" | ||
| echo "" | ||
| echo " 2. In the web terminal, connect with these SSH credentials:" | ||
| 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." | ||
| echo " Cancel this workflow run to shut it down early." | ||
| echo "============================================" |
There was a problem hiding this comment.
This workflow exposes a publicly reachable tunnel to the runner and prints the tunnel URL plus SSH credentials into the build logs. In a public repo, that effectively creates an unauthenticated remote shell environment that anyone who sees the logs can use while the job is running, which is a significant security and abuse risk. Consider replacing the public tunnel with an authenticated/approved access mechanism (e.g., GitHub environments with required reviewers, or a GitHub-provided debugging channel like action-tmate), and avoid emitting reusable credentials into logs.
| - 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 | ||
| DURATION_SECONDS=$(( DURATION_INPUT * 60 )) | ||
| echo "Keeping environment alive for ${DURATION_INPUT} minute(s)..." |
There was a problem hiding this comment.
The duration input is only validated as a positive integer and has no upper bound, so a dispatch can keep a runner allocated up to the GitHub job timeout (hours), increasing cost/queue pressure. Add a reasonable maximum duration (and/or set timeout-minutes on the job) and clamp the input to that max.
|
@copilot apply changes based on the comments in this thread, and add windows test |
Agent-Logs-Url: https://github.com/ohto-ai/webssh_cpp/sessions/0c9f942a-3177-4e23-ace0-3aa373be5981 Co-authored-by: ohto-ai <46275725+ohto-ai@users.noreply.github.com>
Applied all review feedback and added Windows test support in aa58e62: test.yaml:
manual_test.yaml:
|
|
@copilot |
Agent-Logs-Url: https://github.com/ohto-ai/webssh_cpp/sessions/af1abb93-13c9-47ce-a70c-68c2f00d17d2 Co-authored-by: ohto-ai <46275725+ohto-ai@users.noreply.github.com>
Done in 313dade. Added a |
Adds two GitHub Actions workflows to enable automated test execution and on-demand human testing of the running application.
test.yaml— Test CI (workflow_dispatch)workflow_dispatch(avoids duplicate push/PR runs alongsideci.yaml)ubuntu-22.04,ubuntu-latest, andwindows-latestopenssh-server(withapt-get update), enables password auth, and creates a test user with a cryptographically random password (openssl rand -hex 8)OpenSSH.Servercapability, startssshd, and creates a local test user with a cryptographically secure password (RandomNumberGenerator.Fill)TEST_SSH_HOST/PORT/USER/PASSenv vars so thatssh_connection.test.cppintegration tests have a real SSH target (they skip gracefully whenTEST_SSH_HOSTis unset)webssh_cpp_tests(Debug) and runsctest --output-on-failuretimeout-minutes: 60manual_test.yaml— Manual test environment (workflow_dispatch)passwordinput for the test SSH account (webssh_tester); leave it blank to auto-generate a random password — the value is passed via an environment variable to prevent shell injectiondurationinput (minutes, default 30, max 60) for how long to keep the environment alivewebssh_cpp(Release) and starts it on port 8080action-tmate(detached, restricted to the workflow triggerer vialimit-access-to-actor: true) — no public tunnel; testers use SSH port-forwarding from the tmate session to reachhttp://localhost:8080/127.0.0.1:22)timeout-minutes: 65enforces a hard ceilingBoth jobs use
permissions: contents: readfor least-privilegeGITHUB_TOKENaccess.