Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
745 changes: 745 additions & 0 deletions .github/actions/gwy/badges/action.yml

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions .github/actions/gwy/coverage/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
name: 'Unit Tests & Coverage'
description: 'Runs Go tests, checks coverage and updates badge'

inputs:
threshold:
description: 'Minimum coverage threshold (%)'
required: true

token:
description: 'GitHub token for pushing badges'
required: false

summary-threshold:
description: 'Minimum coverage threshold (%) of functions showed in summary'
required: false
default: '51'

outputs:
result:
description: 'Result of the coverage check (success or failed)'
value: ${{ steps.check-coverage.outputs.result }}

runs:
using: 'composite'
steps:
- name: Run Tests with Coverage
shell: bash
run: |
# Running unit tests and coverage
GWY_COVER=cover.out
echo "GWY_COVER=$GWY_COVER" >> $GITHUB_ENV

echo "GWY_ARTIFACT=$RUNNER_TEMP/coverage-report.md" >> $GITHUB_ENV
echo "GWY_SUMMARY=$RUNNER_TEMP/coverage-summary.md" >> $GITHUB_ENV

# set annotations reusable title
echo "GWY_TITLE=coverage threshold check" >> $GITHUB_ENV

# run unit tests and generate coverage dump
GWY_GO_TEST="$(timeout $GWY_TIMEOUT_SECONDS go test ./... -coverprofile="$GWY_COVER" -covermode=atomic -coverpkg=./... 2>&1)"
echo "GWY_GO_TEST<<EOF" >> $GITHUB_ENV
echo "$GWY_GO_TEST" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV

echo "$GWY_GO_TEST"

# process coverage dump
GWY_GO_TOOL=$(go tool cover -func="$GWY_COVER" 2>&1)
echo "GWY_GO_TOOL<<EOF" >> $GITHUB_ENV
echo "$GWY_GO_TOOL" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV

echo "$GWY_GO_TOOL"

# process coverage results
# timeout $GWY_TIMEOUT_SECONDS go tool cover -func=$GWY_COVER | grep "total:" | awk '{print "Total Coverage: " $3}'
GWY_COVERAGE=$(echo "$GWY_GO_TOOL" | grep 'total:' | awk '{print $3}' | sed 's/%//' | xargs printf "%.0f")
echo "GWY_COVERAGE=$GWY_COVERAGE" >> $GITHUB_ENV

echo "Coverage Total: $GWY_COVERAGE"

- name: Check Coverage Threshold
id: check-coverage
continue-on-error: true

shell: bash
run: |
# Checking Coverage Threshold
GWY_THRESHOLD=${{ inputs.threshold }}
GWY_TOTAL_COVERAGE=${{ env.GWY_COVERAGE }}

if (( $(echo "$GWY_TOTAL_COVERAGE < $GWY_THRESHOLD" | bc -l) )); then
echo "::error title=$GWY_TITLE: NOT MET::coverage ($GWY_TOTAL_COVERAGE%) is below threshold ($GWY_THRESHOLD%)"
echo "Coverage ($GWY_TOTAL_COVERAGE%) is below threshold ($GWY_THRESHOLD%)"
echo "result=failed" >> $GITHUB_OUTPUT
else
echo "::notice title=$GWY_TITLE: success::coverage ($GWY_TOTAL_COVERAGE%) meets threshold ($GWY_THRESHOLD%)"
echo "congratulations! coverage ($GWY_TOTAL_COVERAGE%) meets threshold ($GWY_THRESHOLD%)"
echo "result=success" >> $GITHUB_OUTPUT
fi

- name: Add Coverage Summary to Job
if: always()
continue-on-error: true
shell: bash
run: |
# Generating Coverage Summary
echo "## Code Coverage" >> $GWY_SUMMARY

# Capture coverage output
GWY_COVERAGE_LINES=$(echo "$GWY_GO_TOOL" | grep -v "total:")

# Check if GWY_COVERAGE_LINES is empty
if [ -z "$GWY_COVERAGE_LINES" ]; then
echo " - no tests found in repository" >> $GWY_SUMMARY
else
echo "$GWY_COVERAGE_LINES" | while IFS=: read -r full_path line rest; do
file=$(basename "$full_path")
relative_path=$(echo "$full_path" | sed 's|github.com/[^/]\+/[^/]\+/||')
func_percent=$(echo "$rest" | sed 's/^\s*//')
func=$(echo "$func_percent" | awk '{print $1}')
percent=$(echo "$func_percent" | awk '{print $2}' | sed 's/%$//') # Strip % for comparison
# Compare coverage against threshold (convert to int for -lt)
if [ $(echo "$percent < ${{ inputs.summary-threshold }}" | bc) -eq 1 ]; then
url="https://github.com/${GITHUB_REPOSITORY}/blob/${GWY_BRANCH}/${relative_path}#L${line}"
printf ' - `%-8s` [%s()](%s)\n' "${percent}%" "$func" "$url" >> $GWY_SUMMARY
fi
done

echo -e " - \`COVERAGE\` ${{ env.GWY_COVERAGE }}%" >> $GWY_SUMMARY

if [ ${{ env.GWY_COVERAGE }} -lt ${{ inputs.threshold }} ]; then
echo -e "\n \n![RESULT:FAILED](https://img.shields.io/badge/result-failed-red?style=for-the-badge)" >> $GWY_SUMMARY
else
echo -e "\n \n![RESULT:SUCCESS](https://img.shields.io/badge/result-success-green?style=for-the-badge)" >> $GWY_SUMMARY
fi
fi

cat $GWY_SUMMARY >> $GITHUB_STEP_SUMMARY

# append to artifact coverage output

cat $GWY_SUMMARY_HEADING > $GWY_ARTIFACT
cat $GWY_SUMMARY >> $GWY_ARTIFACT

echo -e "\n\n## Coverage Output\n" >> $GWY_ARTIFACT
echo -e "### go test\n \n\`\`\`\n$GWY_GO_TEST\n\`\`\`\n" >> $GWY_ARTIFACT
echo -e "### go tool cover\n \n\`\`\`\n$GWY_GO_TOOL\n\`\`\`\n" >> $GWY_ARTIFACT

echo -e "### cover.out\n \n\`\`\`\n" >> $GWY_ARTIFACT
cat $GWY_COVER >> $GWY_ARTIFACT
echo -e "\n\`\`\`\n" >> $GWY_ARTIFACT

- name: Upload Coverage Summary Artifact
if: always()
continue-on-error: true

uses: actions/upload-artifact@v4
with:
name: coverage-report
path: ${{ env.GWY_ARTIFACT }}

- name: Action clean-up
shell: bash
run: |
# Cleaning Action Environment
unset GWY_TITLE
unset GWY_COLOR
unset GWY_COVERAGE
unset GWY_THRESHOLD
unset GWY_TOTAL_COVERAGE
unset GWY_COVERAGE_LINES

rm -f cover.out
162 changes: 162 additions & 0 deletions .github/actions/gwy/dependencies/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
name: 'Dependencies Scan'
description: 'Scans for outdated Go dependencies and optionally creates a PR with updates'

inputs:
token:
description: 'Repository token for PR creation (required if create-pr is true)'
required: false

create-pr:
description: 'Create a PR with outdated dependency updates?'
required: true
default: 'true'

outputs:
result:
description: 'Result of the action (success or failed)'
value: ${{ steps.check-dependencies.outputs.result }}

runs:
using: 'composite'
steps:
- name: Initialize Dependencies Scanning Environment
shell: bash
run: |
# Initialize Dependencies Scanning Environment
GWY_SUMMARY=$RUNNER_TEMP/dependencies-summary.txt
echo -e "## Outdated Dependencies Scan\n" >> $GWY_SUMMARY

# set annotations reusable title
echo "GWY_TITLE=outdated dependencies scan" >> $GITHUB_ENV

# export reusable environments
echo "GWY_SUMMARY=$GWY_SUMMARY" >> $GITHUB_ENV
echo "GWY_DEPENDENCIES_COUNT=0" >> $GITHUB_ENV
echo "GWY_ARTIFACT=$RUNNER_TEMP/dependencies-report.md" >> $GITHUB_ENV
echo "GWY_BRANCH=$(git branch --show-current)" >> $GITHUB_ENV
sync

- name: Check Outdated Dependencies
id: check-dependencies
continue-on-error: true

# Allow pipeline to keep going on errors (+e)
shell: bash --noprofile --norc +e -o pipefail {0}
run: |
# Check Outdated Dependencies

# Update dependencies and tidy, suppress output
timeout $GWY_TIMEOUT_SECONDS sh -c "go get -u ./... 2>&1 | grep '^go: upgraded ' | sed 's/go: upgraded //'"

# Save dependency updates found for report
GWY_DEPENDENCIES_FOUND=$(git diff -U0 go.mod | grep -E '^\-[^+-]')

# GWY_DEPENDENCIES_COUNT=$(echo "$GWY_DEPENDENCIES_FOUND" | wc -l)
# process outdated dependencies count
if [ -z "$GWY_DEPENDENCIES_FOUND" ]; then
GWY_DEPENDENCIES_COUNT=0
else
GWY_DEPENDENCIES_COUNT=$(echo "$GWY_DEPENDENCIES_FOUND" | wc -l)
fi

echo "GWY_DEPENDENCIES_COUNT=$GWY_DEPENDENCIES_COUNT" >> $GITHUB_ENV

# set action result based in outdated dependencies count
if [ "$GWY_DEPENDENCIES_COUNT" -ne 0 ]; then
echo "result=failed" >> $GITHUB_OUTPUT
else
echo "result=success" >> $GITHUB_OUTPUT
fi

# Write diff to artifact
git diff go.mod > $GWY_ARTIFACT

# remove go.mod changes if no pr creation was requested
if [ "${{ inputs.create-pr }}" != "true" ]; then
echo "unstaging changes"
git restore go.mod go.sum
fi

# Enhance summary, annotations, and debug output
if [ $GWY_DEPENDENCIES_COUNT -ne 0 ]; then
# Error annotation with count
echo "::error title=$GWY_TITLE: $GWY_DEPENDENCIES_COUNT OUTDATED DEPENDENCIES!::check summary or artifact report for more details"

# Add to summary
echo "$GWY_DEPENDENCIES_FOUND" | sed 's/^/ /' >> $GWY_SUMMARY

else
# Success annotation
echo "::notice title=$GWY_TITLE: up-to-date::code dependencies in go.mod are up-to-date"

# Add to summary
echo " - no outdated dependencies detected" >> $GWY_SUMMARY
fi

cat $GWY_SUMMARY >> $GITHUB_STEP_SUMMARY

# append to artifact dependencies scan output

echo -e "\n\n## Dependencies Scan Output\n\n\`\`\`" >> $GWY_SUMMARY
cat $GWY_ARTIFACT >> $GWY_SUMMARY
echo -e "\`\`\`\n" >> $GWY_SUMMARY

cat $GWY_SUMMARY_HEADING > $GWY_ARTIFACT
cat $GWY_SUMMARY >> $GWY_ARTIFACT

- name: Create PR with Updates
id: create-pr
if: env.GWY_DEPENDENCIES_COUNT != '0' && inputs.create-pr == 'true'

continue-on-error: true
uses: peter-evans/create-pull-request@v5

with:
token: ${{ inputs.token }}
title: "[GWY/CI] Automatic outdated dependencies fix (${{ env.GWY_BRANCH }})"
body: "Automatic update of ${{ env.GWY_DEPENDENCIES_COUNT }} outdated dependencies"
commit-message: "[GWY/CI] automatic fix of ${{ env.GWY_DEPENDENCIES_COUNT }} outdated dependencies"
branch: ${{ env.GWY_BRANCH }}-dependencies-fix

- name: Notify PR Creation Result
if: env.GWY_DEPENDENCIES_COUNT != '0' && inputs.create-pr == 'true'

# Allow pipeline to keep going on errors (+e)
shell: bash --noprofile --norc +e -o pipefail {0}
continue-on-error: true

run: |
# Check if PR was created successfully
if [ "${{ steps.create-pr.outcome }}" == "success" ]; then
echo "::notice title=$GWY_TITLE: PR created::PR with code outdated dependencies update created"
else
echo "::error title=$GWY_TITLE: ERROR CREATING PULL REQUEST::Failed to create PR with dependencies updates"
fi

- name: Upload Outdated Dependencies Report
if: always()
continue-on-error: true

uses: actions/upload-artifact@v4
with:
name: dependencies-report
path: ${{ env.GWY_ARTIFACT }}

- name: Step Clean-Up
if: always()
shell: bash
run: |
# Dependencies Scanning Clean-Up

# remove temporary files
rm -f $GWY_SUMMARY
rm -f $GWY_ARTIFACT

# Unset variables
unset GWY_TITLE
unset GWY_SUMMARY
unset GWY_ARTIFACT
unset GWY_PIPELINE_STATUS
unset GWY_TIMEOUT_SECONDS
unset GWY_DEPENDENCIES_FOUND
unset GWY_DEPENDENCIES_COUNT
Loading