Skip to content

Conversation

lcatlett
Copy link
Member

@lcatlett lcatlett commented Apr 2, 2025

Problem

The current Terminus installation process has several reliability issues:

  1. It lacks validation of the download's success.
  2. It fails to verify the integrity of the downloaded file.
  3. Utilizing the latest version without validation results in non-deterministic builds.
  4. Error reporting is inadequate, hindering troubleshooting efforts.

These issues have affected a few Pantheon customers, one of which recently encountered hard-to-diagnose failures in their CI pipelines. Errors such as /usr/local/bin/terminus: line 1: Not: command not found were observed, indicating a download failure while the workflow proceeded, causing significant workflow disruptions and troubleshooting challenges.

Solution

This pull request addresses these issues by:

  1. Enhancing version selection with rigorous validation.
  2. Implementing download validation using curl --fail.
  3. Verifying the SHA256 checksum of the downloaded file.
  4. Adding basic file type verification.
  5. Enhancing error reporting for improved troubleshooting.
  6. Verifying the installation with terminus --version.

Implementation Details

1. Improved Version Selection

  • The existing approach of fetching the latest version is retained but enhanced with strict validation.
  • If the GitHub API request fails or returns an invalid version string, the workflow terminates with a clear error message.
  • The input parameter description now recommends specifying a version for deterministic builds.
  • There is no fallback to hardcoded versions; either the version is accurately detected or the user must specify one.

These modifications enhance the reliability of the action and mitigate common installation failures while preserving compatibility with existing workflows that explicitly specify a version.

Code Changes

The pull request updates the "Set Terminus version" and "Install Terminus" steps in action.yml to incorporate these enhancements:

  1. Implemented robust validation for the version retrieval process.
  2. Enhanced download validation with improved error reporting capabilities.
  3. Introduced checksum verification to ensure the integrity of the downloaded files.
  4. Added file type validation to ensure compatibility with the intended file formats.
  5. Implemented installation verification to confirm the successful completion of the installation process.

Users who explicitly specify a version using the terminus-version parameter will continue to experience the same behavior, but the reliability of the action has been significantly improved. Users who rely on automatic version detection will benefit from enhanced error handling and clear failure messages, providing more timely feedback in the event of installation issues.

These modifications directly address the challenges faced by Pantheon customers running into CI failures with errors like line 1: Not: command not found by promptly identifying and resolving installation problems as the root cause, rather than allowing them to recur later with cryptic error messages that can hinder development velocity and consume troubleshooting time for both customers and support teams trying to diagnose issues originating in the CI configuration.

@lcatlett lcatlett requested a review from a team as a code owner April 2, 2025 00:26
@pwtyler
Copy link
Member

pwtyler commented Apr 2, 2025

Download of both phar and checksum failing, flipping to draft until ready for re-review.

@pwtyler pwtyler marked this pull request as draft April 2, 2025 01:26
description: Disable session cache and force a new session to be initiated.
required: false
default: false
default: "false"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for switching this from boolean to string?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe GHA really handle bool properly in these configs. IIRC, false is already a string, ^ just makes it more explicit.

curl --silent \
echo "Attempting to find latest Terminus version..."
# Try to get the latest release from GitHub API with proper error handling
if ! TERMINUS_RELEASE=$(curl --silent --fail --max-time 10 \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why constrain max-time to 10 seconds for everyone? Could this be made a configuration option rather than hard-coded?

| perl -nle'print $& while m#"tag_name": "\K[^"]*#g'
)
| perl -nle'print $& while m#"tag_name": "\K[^"]*#g'); then
echo "::error::Failed to connect to GitHub API to determine latest Terminus version."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This request could fail for a lot of reasons that weren't a connection failure; if there is any http response code at all then the connection was successful.

)
| perl -nle'print $& while m#"tag_name": "\K[^"]*#g'); then
echo "::error::Failed to connect to GitHub API to determine latest Terminus version."
echo "::error::Please specify a terminus-version input parameter for deterministic builds."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again I don't think we should assert that all users should hard-code their terminus version. Some customers will want deterministic builds, other users will want to stay on the latest version.

terminus-version:
description: |
The full version of Terminus to install. If omitted, the latest version is used.
For deterministic builds, specifying a version is recommended.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For deterministic builds, specifying a version is recommended.
Specifying a version provides deterministic results in exchange for not always having the latest version, with the caveat that deprecated versions will eventually be rejected by the the back-end.

I like the idea of calling out specifying a version for deterministic results builds, but I don't think we want to make that a blanket recommendation for all users. Terminus evolves over time and we plan to begin hard-refusing requests from deprecated versions server-side in the near future.

Hard-coding a version would mean the customer would need to update their CI configuration from time to time. For larger enterprise customers, that's a reasonable tradeoff, but it's not a good tradeoff for everyone.

Comment on lines +40 to +41
echo "::error::Unable to determine a valid Terminus version from GitHub API."
echo "::error::Please specify a terminus-version input parameter for deterministic builds."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current error handling buries any indication of what exactly went wrong. Yes, the current code suffers from that same problem, but while we're improving error handling we should also improve visibility into the details of the error. At minimum, if this condition fails, the value of $TERMINUS_RELEASE should be printed in the error message. Depending on what has gone wrong, $TERMINUS_RELEASE may be empty, and there are probably ways to get more detailed information fro curl about the nature of the problem.

Comment on lines +60 to +72
# Download checksum for verification
if curl --fail -L https://github.com/pantheon-systems/terminus/releases/download/$TERMINUS_RELEASE/terminus.phar.sha256 --output terminus.sha256; then
echo "Verifying download integrity..."
# Fix the checksum file format if needed (ensure it only contains hash and filename)
sed -i.bak 's/^.*\([0-9a-f]\{64\}\).*$/\1 terminus/g' terminus.sha256
if ! sha256sum -c terminus.sha256; then
echo "::error::Checksum verification failed! The downloaded file may be corrupted."
exit 1
fi
echo "Integrity verification passed."
else
echo "::warning::Could not download checksum file. Skipping integrity check."
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This checksum check should be removed, at least for now. That file doesn't exist, so currently this is just adding another request which is guaranteed to fail.

Comment on lines +74 to +79
# Basic file type verification
file_info=$(file terminus)
if ! echo "$file_info" | grep -q -E 'PHP script|executable|.+ASCII.+PHP'; then
echo "::error::Downloaded file is not a PHP script or executable. Got: $file_info"
exit 1
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File type check should be removed. The output of the file command is not consistent across systems, and it's clear you've already encountered this since the grep is attempting to match 3 different possible responses.

It is receiving a different response in Github Actions than what the pattern match currently covers. Adding more conditions to account for this additional format will still not provide full coverage. Additionally it assumes that the file command exists, which will not always be the case.

This check is also made redundant by the terminus --version test at the end. That test will not succeed if what's downloaded isn't the correct type.

@stevector
Copy link

@lcatlett what would you think of moving the GitHub Action that installs Terminus to the Terminus repo?

Here's an example of from Deno where the repo containing the command line tool also contains the Action to install that version: https://github.com/denoland/deployctl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants