diff --git a/.github/workflows/publish_su2_validation.yml b/.github/workflows/publish_su2_validation.yml new file mode 100644 index 00000000..f6a8d779 --- /dev/null +++ b/.github/workflows/publish_su2_validation.yml @@ -0,0 +1,377 @@ +name: Publish SU2 Validation Test Cases Results + +on: + workflow_dispatch: + inputs: + branch_name: + description: "SU2 Branch Checked Out (e.g. master, develop)" + required: true + type: choice + options: + - master + - develop + case_code: + description: "Validation Case Code (e.g. 2DML)" + required: true + type: choice + options: + - 2DML + - All + case_name: + description: "Validation Case Name (e.g. 2D Mixing Layer)" + required: true + type: choice + options: + - 2D Mixing Layer + - All + flow_condition: + description: "Incompressible Flow or Compressible Flow" + required: true + type: choice + options: + - Incompressible Flow + - Compressible Flow + - All + author_name: + description: "Author's Name (e.g. Harsh)" + required: true + type: string + +env: + SANITIZED_AUTHOR: "Automated_Update" + +jobs: + process-and-publish: + runs-on: ubuntu-latest + steps: + - name: Validate Inputs + run: | + echo "Validating workflow inputs..." + + CASE_CODE="${{ github.event.inputs.case_code }}" + CASE_NAME="${{ github.event.inputs.case_name }}" + FLOW_CONDITION="${{ github.event.inputs.flow_condition }}" + + ERRORS="" + + if [[ "$CASE_CODE" == "All" && "$CASE_NAME" != "All" ]]; then + ERRORS+="\n'All' case code cannot be paired with a specific case name ($CASE_NAME)" + fi + + if [[ "$CASE_CODE" != "All" && "$CASE_NAME" == "All" ]]; then + ERRORS+="\nSpecific case code ($CASE_CODE) cannot be paired with 'All' case name" + fi + + if [[ "$CASE_CODE" != "All" && "$FLOW_CONDITION" == "All" ]]; then + ERRORS+="\nSpecific case code ($CASE_CODE) cannot be paired with 'All' flow condition" + fi + + if [[ "$CASE_CODE" == "All" && "$FLOW_CONDITION" != "All" ]]; then + ERRORS+="\n'All' case code must also have 'All' flow condition" + fi + + if [[ -n "$ERRORS" ]]; then + echo "::error::Input Validation Failed:$ERRORS" + echo "Tip: Use either all 'All' values or all specific values for a single run." + exit 1 + fi + + echo "Inputs are valid. Continuing..." + + - name: Sanitize Author's Name + run: | + SANITIZED=$(echo "${{ github.event.inputs.author_name }}" | + tr -d '\n' | # Remove newlines + tr ' ' '_' | # Convert spaces + tr -s '_' | # Collapse multiple ____ + sed 's/^_\+//; s/_\+$//' | # Trim leading/trailing _ + tr -dc '[:alnum:]_' | # Strict character set + head -c 50) + + # Fallback Conditions + if [[ -z "$SANITIZED" || "$SANITIZED" =~ ^[0-9_]+$ ]]; then + SANITIZED="Automated_Update" + fi + echo "SANITIZED_AUTHOR=${SANITIZED}" >> $GITHUB_ENV + + - name: Checkout Develop Branch + uses: actions/checkout@v4 + with: + ref: develop + + - name: Check If Target Branch Exists + id: branch-check + env: + TARGET_BRANCH: "ValidationCases_${{ github.event.inputs.branch_name}}_${{ env.SANITIZED_AUTHOR }}" + run: | + if git ls-remote --heads origin $TARGET_BRANCH | grep -q $TARGET_BRANCH; then + echo "Branch $TARGET_BRANCH exists. Proceeding..." + echo "branch_exists=true" >> $GITHUB_OUTPUT + else + echo "::error::Branch $TARGET_BRANCH does not exist. Aborting." + echo "branch_exists=false" >> $GITHUB_OUTPUT + exit 1 + fi + + - name: Checkout Target Branch + if: steps.branch-check.outputs.branch_exists == 'true' + uses: actions/checkout@v4 + with: + ref: "ValidationCases_${{ github.event.inputs.branch_name}}_${{ env.SANITIZED_AUTHOR }}" + token: ${{ secrets.GITHUB_TOKEN }} + persist-credentials: true + fetch-depth: 0 + + - name: Prepare Markdown File For All Validation Cases + if: steps.branch-check.outputs.branch_exists == 'true' && inputs.case_code == 'All' && inputs.case_name == 'All' + run: | + BASE_PATH="vandv_files" + TEMPLATE="template_README.md" + OUTPUT_DIR="_vandv" + OUTPUT_FILE="${OUTPUT_DIR}/All_Validation_Cases.md" + + for case_dir in "$BASE_PATH"/*/; do + if [ -d "$case_dir" ] && [[ "$(basename "$case_dir")" != .* ]]; then + casecode=$(basename "$case_dir") + IMAGE_COUNT=0 + IMAGE_DIR="vandv_files/${casecode}" + + # Validate inputs and paths + if [ ! -f "${TEMPLATE}" ]; then + echo "::error::Template ${TEMPLATE} not found!" + exit 1 + fi + + if [ ! -d "${OUTPUT_DIR}" ]; then + echo "::error::Directory ${OUTPUT_DIR} must exist in the repository. Deploy it first." + exit 1 + fi + + if [ ! -d "${IMAGE_DIR}" ]; then + echo "::error::Image directory ${IMAGE_DIR} not found!" + exit 1 + fi + + if ! grep -q '{Case_Code}' "${TEMPLATE}" || ! grep -q 'Your Case Study Title' "${TEMPLATE}"; then + echo "::error::Template missing required placeholders" + exit 1 + fi + + # Update front matter and write to new file + sed \ + -e "s/{Case_Code}/All_Validation_Cases/g" \ + -e "s/Your Case Study Title/All Validation Cases/g" \ + "${TEMPLATE}" > "${OUTPUT_FILE}" + + # Count images first + IMAGE_COUNT=$(find "${IMAGE_DIR}" -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.jpeg" \) | wc -l) + + if [ "${IMAGE_COUNT}" -eq 0 ]; then + echo "::error::ABORTING: No plot images found in ${IMAGE_DIR}/" + rm -f "${OUTPUT_FILE}" # Delete the empty Markdown file + exit 1 + fi + + echo -e "\n## Results Plots For ${casecode}\n" >> "${OUTPUT_FILE}" + + # Find and process images + find "${IMAGE_DIR}" -type d -name "${casecode}_*" | sort | while read -r dir; do + folder_name=$(basename "${dir}") + echo -e "\n### ${folder_name}\n" >> "${OUTPUT_FILE}" + + # Process images with their relative path + find "${dir}" -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.jpeg" \) | sort | while read -r img; do + # Calculate relative path + rel_path="../${img#*/vandv_files/}" + echo "\"${folder_name}" >> "${OUTPUT_FILE}" + echo "" >> "${OUTPUT_FILE}" + done + done + fi + done + # Verify creation + echo "Generated ${OUTPUT_FILE}" + + - name: Prepare Markdown File For Specific Validation Case + if: steps.branch-check.outputs.branch_exists == 'true' && inputs.case_code != 'All' && inputs.case_name != 'All' + run: | + # Initialize variables + IMAGE_COUNT=0 + SANITIZED_CASE_NAME=$(echo "${{ github.event.inputs.case_name }}" | tr -dc '[:alnum:] ') + SANITIZED_CASE_CODE=$(echo "${{ github.event.inputs.case_code }}" | tr -dc '[:alnum:]' | tr '[:lower:]' '[:upper:]') + + # Define paths + TEMPLATE="template_README.md" + OUTPUT_DIR="_vandv" + OUTPUT_FILE="${OUTPUT_DIR}/${SANITIZED_CASE_CODE}.md" + IMAGE_DIR="vandv_files/${SANITIZED_CASE_CODE}" + + # Validate inputs and paths + if [ ! -f "${TEMPLATE}" ]; then + echo "::error::Template ${TEMPLATE} not found!" + exit 1 + fi + + if [ ! -d "${OUTPUT_DIR}" ]; then + echo "::error::Directory ${OUTPUT_DIR} must exist in the repository. Deploy it first." + exit 1 + fi + + if [ ! -d "${IMAGE_DIR}" ]; then + echo "::error::Image directory ${IMAGE_DIR} not found!" + exit 1 + fi + + if ! grep -q '{Case_Code}' "${TEMPLATE}" || ! grep -q 'Your Case Study Title' "${TEMPLATE}"; then + echo "::error::Template missing required placeholders" + exit 1 + fi + + # Update front matter and write to new file + sed \ + -e "s/{Case_Code}/${SANITIZED_CASE_CODE}/g" \ + -e "s/Your Case Study Title/${SANITIZED_CASE_NAME}/g" \ + "${TEMPLATE}" > "${OUTPUT_FILE}" + + # Count images first + IMAGE_COUNT=$(find "${IMAGE_DIR}" -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.jpeg" \) | wc -l) + + if [ "${IMAGE_COUNT}" -eq 0 ]; then + echo "::error::ABORTING: No plot images found in ${IMAGE_DIR}/" + rm -f "${OUTPUT_FILE}" # Delete the empty Markdown file + exit 1 + fi + + echo -e "\n## Results Plots\n" >> "${OUTPUT_FILE}" + + # Find and process images + find "${IMAGE_DIR}" -type d -name "${SANITIZED_CASE_CODE}_*" | sort | while read -r dir; do + folder_name=$(basename "${dir}") + echo -e "\n### ${folder_name}\n" >> "${OUTPUT_FILE}" + + # Process images with their relative path + find "${dir}" -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.jpeg" \) | sort | while read -r img; do + # Calculate relative path + rel_path="../${img#*/vandv_files/}" + echo "\"${folder_name}" >> "${OUTPUT_FILE}" + echo "" >> "${OUTPUT_FILE}" + done + done + + # Verify creation + echo "Generated ${OUTPUT_FILE}" + + - name: Install yq (Go version) + run: | + sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 + sudo chmod +x /usr/local/bin/yq + yq --version + + - name: Update V&V Listing + if: steps.branch-check.outputs.branch_exists == 'true' + run: | + # Verify yq installation + if ! command -v yq &>/dev/null; then + echo "::error::yq not installed" + exit 1 + fi + + VANDV_YML="_data/vandv.yml" + + # Verify file exists + if [ ! -f "${VANDV_YML}" ]; then + echo "::error::YAML file ${VANDV_YML} not found" + exit 1 + fi + + # Create backup + cp "${VANDV_YML}" "${VANDV_YML}.bak" + + if [ "${{ github.event.inputs.flow_condition }}" == "All" ]; then + NEW_SECTION_TITLE="All Validation Cases" + NEW_ENTRY="All_Validation_Cases" + + # Check if section exists + SECTION_EXISTS=$(yq eval ".[] | select(.title == \"${NEW_SECTION_TITLE}\") | length" "${VANDV_YML}") + + if [ "${SECTION_EXISTS}" -gt 0 ]; then + echo "Section '${NEW_SECTION_TITLE}' already exists. No changes made." + else + echo "Adding new '${NEW_SECTION_TITLE}' section..." + + # Create new section in a temporary file + TEMP_FILE=$(mktemp) + trap 'rm -f "${TEMP_FILE}" "${VANDV_YML}.tmp"' EXIT + echo "- title: ${NEW_SECTION_TITLE}" > "${TEMP_FILE}" + echo " vandv:" >> "${TEMP_FILE}" + echo " - ${NEW_ENTRY}" >> "${TEMP_FILE}" + + # Merge with existing content + yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' "${VANDV_YML}" "${TEMP_FILE}" > "${VANDV_YML}.tmp" + + # Verify merge was successful + MERGED_COUNT=$(yq eval 'length' "${VANDV_YML}.tmp") + ORIGINAL_COUNT=$(yq eval 'length' "${VANDV_YML}") + + if [ "${MERGED_COUNT}" -le "${ORIGINAL_COUNT}" ]; then + echo "::error::Failed to properly merge new section" + rm -f "${TEMP_FILE}" "${VANDV_YML}.tmp" + mv "${VANDV_YML}.bak" "${VANDV_YML}" + exit 1 + fi + + # Verify new section exists in merged file + if [ $(yq eval ".[] | select(.title == \"${NEW_SECTION_TITLE}\") | length" "${VANDV_YML}.tmp") -eq 0 ]; then + echo "::error::New section not found in merged file" + rm -f "${TEMP_FILE}" "${VANDV_YML}.tmp" + mv "${VANDV_YML}.bak" "${VANDV_YML}" + exit 1 + fi + + # Replace original file if all checks pass + mv "${VANDV_YML}.tmp" "${VANDV_YML}" + echo "Successfully added new section while preserving existing content" + rm -f "${TEMP_FILE}" + fi + else + CASE_CODE="${{ github.event.inputs.case_code }}" + FLOW_TYPE="${{ github.event.inputs.flow_condition }}" + + # Check if case exists + EXISTS=$(yq eval ".[] | select(.title == \"${FLOW_TYPE}\").vandv[] | select(. == \"${CASE_CODE}\")" "${VANDV_YML}") + if [ -n "${EXISTS}" ]; then + echo "Case ${CASE_CODE} already exists. Skipping update." + rm -f "${VANDV_YML}.bak" + exit 0 + fi + + # Update YAML + yq eval -i ".[] |= (select(.title == \"${FLOW_TYPE}\").vandv += [\"${CASE_CODE}\"])" "${VANDV_YML}" + + # Verify update + UPDATED=$(yq eval ".[] | select(.title == \"${FLOW_TYPE}\").vandv[] | select(. == \"${CASE_CODE}\")" "${VANDV_YML}") + if [ -z "${UPDATED}" ]; then + echo "::error::Failed to add case code to YAML" + mv "${VANDV_YML}.bak" "${VANDV_YML}" + exit 1 + fi + fi + + echo "Successful update to vandv.yml" + rm -f "${VANDV_YML}.bak" + + - name: Commit And Push Changes + if: steps.branch-check.outputs.branch_exists == 'true' + run: | + git config --global user.name "GitHub Actions" + git config --global user.email "actions@github.com" + + git add . + git status + + if ! git diff-index --quiet HEAD --; then + git commit -m "Automated Update" + git push origin HEAD:"ValidationCases_${{ github.event.inputs.branch_name}}_${{ env.SANITIZED_AUTHOR }}" + else + echo "No changes to commit" + fi diff --git a/template_README.md b/template_README.md new file mode 100644 index 00000000..c4c41bd4 --- /dev/null +++ b/template_README.md @@ -0,0 +1,6 @@ +--- +title: Your Case Study Title +permalink: /vandv/{Case_Code}/ +--- + +