Skip to content

Commit fcac4f4

Browse files
authored
feat: add tests, workflows, and minor display tweaks (#2)
1 parent d72e775 commit fcac4f4

18 files changed

Lines changed: 1434 additions & 46 deletions

.github/.gitversion.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
mode: ContinuousDeployment
2+
tag-prefix: v
3+
increment: None
4+
commit-message-incrementing: Enabled
5+
major-version-bump-message: '^(feat|fix|chore|ci|docs|test)(\(.+\))?\!:.*'
6+
minor-version-bump-message: '^feat(\(.+\))?:.*'
7+
patch-version-bump-message: '^(fix|ci)(\(.+\))?:.*'
8+
branches:
9+
main:
10+
is-main-branch: true
11+
increment: None
12+
feature:
13+
label: alpha
14+
regex: ^(feat(ure)?|(bug)?fix)[\/-](?<BranchName>.+)
15+
increment: None
16+
release:
17+
label: rc
18+
regex: ^releases?[\/-](?<BranchName>.+)
19+
increment: None
20+
ignore:
21+
sha: []
22+
merge-message-formats: {}

.github/workflows/pr.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: pr
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
7+
jobs:
8+
validate:
9+
name: validate
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: hwrok/print-workflow-data@v1
13+
14+
- name: checkout
15+
uses: actions/checkout@v6
16+
17+
- name: pnpm
18+
uses: pnpm/action-setup@v4
19+
with:
20+
version: 10
21+
22+
- name: node
23+
uses: actions/setup-node@v6.2.0
24+
with:
25+
node-version-file: '.nvmrc'
26+
cache: 'pnpm'
27+
28+
- name: pnpm install
29+
id: install-deps
30+
run: pnpm install
31+
32+
- name: check - tests
33+
if: always() && steps.install-deps.outcome == 'success'
34+
run: pnpm test
35+
36+
- name: check - formatting
37+
if: always() && steps.install-deps.outcome == 'success'
38+
run: pnpm format
39+
40+
- name: check - spelling
41+
if: always() && steps.install-deps.outcome == 'success'
42+
run: pnpm spellcheck

.github/workflows/release.yml

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: release
2+
3+
on:
4+
workflow_dispatch:
5+
workflow_call:
6+
outputs:
7+
version:
8+
description: 'version'
9+
value: ${{ jobs.release.outputs.version }}
10+
tag:
11+
description: 'version tag'
12+
value: ${{ jobs.release.outputs.tag }}
13+
14+
concurrency:
15+
group: release
16+
17+
jobs:
18+
release:
19+
runs-on: ubuntu-latest
20+
outputs:
21+
version: ${{ steps.compute_version.outputs.semVer }}
22+
tag: ${{ steps.check_tag.outputs.tag }}
23+
permissions:
24+
contents: write
25+
26+
steps:
27+
- uses: hwrok/print-workflow-data@v1
28+
29+
- name: checkout
30+
uses: actions/checkout@v6
31+
with:
32+
fetch-depth: 0
33+
34+
- name: install gitversion
35+
uses: gittools/actions/gitversion/setup@v4
36+
with:
37+
versionSpec: '6.3.x'
38+
preferLatestVersion: true
39+
40+
- name: compute version
41+
id: compute_version
42+
uses: gittools/actions/gitversion/execute@v4
43+
with:
44+
configFilePath: .github/.gitversion.yml
45+
46+
- run: echo "version:${{ steps.compute_version.outputs.semVer }}"
47+
48+
- name: check tag
49+
id: check_tag
50+
run: |
51+
tag="v${{ steps.compute_version.outputs.semVer }}"
52+
echo "tag=$tag" >> $GITHUB_OUTPUT
53+
if git rev-parse "$tag" >/dev/null 2>&1; then
54+
echo "::warning::Tag $tag already exists — skipping release."
55+
else
56+
echo "should_tag=true" >> $GITHUB_OUTPUT
57+
fi
58+
59+
- name: configure git
60+
if: steps.check_tag.outputs.should_tag
61+
run: |
62+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
63+
git config user.name "github-actions[bot]"
64+
65+
- name: create tag
66+
if: steps.check_tag.outputs.should_tag
67+
run: |
68+
tag="${{ steps.check_tag.outputs.tag }}"
69+
git tag "$tag"
70+
git push origin "$tag"
71+
72+
- name: changelog
73+
if: steps.check_tag.outputs.should_tag
74+
id: changelog
75+
run: |
76+
CURRENT_TAG="${{ steps.check_tag.outputs.tag }}"
77+
PREV_TAG=$(git tag --sort=-version:refname | grep -v "$CURRENT_TAG" | head -n 1)
78+
79+
if [ -z "$PREV_TAG" ]; then
80+
PREV_TAG=$(git rev-list --max-parents=0 HEAD)
81+
fi
82+
83+
CHANGELOG=$(git log --pretty="- %s (%h)" "$PREV_TAG".."$CURRENT_TAG")
84+
85+
DELIMITER=$(openssl rand -hex 16)
86+
echo "CHANGELOG<<$DELIMITER" >> $GITHUB_ENV
87+
echo "$CHANGELOG" >> $GITHUB_ENV
88+
echo "$DELIMITER" >> $GITHUB_ENV
89+
90+
- name: update tracking tag
91+
if: steps.check_tag.outputs.should_tag
92+
run: |
93+
SEMVER="${{ steps.compute_version.outputs.semVer }}"
94+
MAJOR_VERSION=$(echo $SEMVER | cut -d '.' -f 1)
95+
TRACKING_TAG="v$MAJOR_VERSION"
96+
97+
git tag -f $TRACKING_TAG
98+
git push origin $TRACKING_TAG -f
99+
100+
- name: create release
101+
if: steps.check_tag.outputs.should_tag
102+
uses: softprops/action-gh-release@v2
103+
with:
104+
tag_name: ${{ steps.check_tag.outputs.tag }}
105+
name: 'Release ${{ steps.check_tag.outputs.tag }}'
106+
body: |
107+
## Release ${{ steps.check_tag.outputs.tag }}
108+
109+
### Changes
110+
${{ env.CHANGELOG }}
111+
draft: false
112+
prerelease: false

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
.claude
12
.idea
3+
node_modules

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v24

.prettierignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Package Managers
2+
package-lock.json
3+
pnpm-lock.yaml
4+
yarn.lock
5+
bun.lock
6+
bun.lockb
7+
8+
# Miscellaneous
9+
/static/
10+
.terraform/

.prettierrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"useTabs": false,
3+
"singleQuote": true,
4+
"quoteProps": "consistent",
5+
"trailingComma": "all",
6+
"printWidth": 100,
7+
"plugins": [],
8+
"overrides": []
9+
}

action.sh

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/env bash
2+
set +eo pipefail
3+
4+
# formats a value for display
5+
# json objects -> aligned key:value table
6+
# other json -> pretty-printed
7+
# non-json / n/a -> raw
8+
format_value() {
9+
local value="$1"
10+
if [ "$value" = "n/a" ] || [ -z "$value" ]; then
11+
echo "n/a"
12+
return
13+
fi
14+
if ! command -v jq >/dev/null 2>&1; then
15+
echo "$value"
16+
return
17+
fi
18+
if echo "$value" | jq -e 'type == "object"' >/dev/null 2>&1; then
19+
echo "$value" | jq -r '
20+
(keys | map(length) | max) as $w |
21+
to_entries[] |
22+
"\(.key + (" " * ($w - (.key | length)))) : \(.value | if type == "string" then . elif type == "null" then "" else tojson end)"
23+
'
24+
return
25+
fi
26+
if echo "$value" | jq -e '.' >/dev/null 2>&1; then
27+
echo "$value" | jq '.'
28+
return
29+
fi
30+
echo "$value"
31+
}
32+
33+
# prints a labeled section with a colored box header
34+
print_section() {
35+
local title="$1"
36+
local body="$2"
37+
local color=92 # bright green
38+
local bar_len=$(( ${#title} + 2 ))
39+
local bar
40+
bar="$(printf '─%.0s' $(seq 1 $bar_len))"
41+
printf '\e[1;%sm┌%s┐\e[0m\n' "$color" "$bar"
42+
printf '\e[1;%sm│ %s │\e[0m\n' "$color" "$title"
43+
printf '\e[1;%sm└%s┘\e[0m\n' "$color" "$bar"
44+
printf '%s\n' "$body"
45+
}
46+
47+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
48+
is_default_branch="false"
49+
is_default_target="false"
50+
[ "$GITHUB_REF_NAME" = "$DEFAULT_BRANCH" ] && is_default_branch="true"
51+
[ "$GITHUB_BASE_REF" = "$DEFAULT_BRANCH" ] && is_default_target="true"
52+
53+
github_context_body=$(cat <<EOF
54+
github.actor : $GITHUB_ACTOR
55+
github.triggering_actor : $TRIGGERING_ACTOR
56+
github.workflow : $GITHUB_WORKFLOW
57+
github.workflow_ref : $GITHUB_WORKFLOW_REF
58+
github.run_id : $GITHUB_RUN_ID
59+
github.run_number : $GITHUB_RUN_NUMBER
60+
github.run_attempt : $GITHUB_RUN_ATTEMPT
61+
github.event_name : $GITHUB_EVENT_NAME
62+
github.event.action : $EVENT_ACTION
63+
github.base_ref : $GITHUB_BASE_REF
64+
github.head_ref : $GITHUB_HEAD_REF
65+
is_default_branch : $is_default_branch
66+
is_default_target : $is_default_target
67+
github.ref : $GITHUB_REF
68+
github.ref_name : $GITHUB_REF_NAME
69+
github.sha : $GITHUB_SHA
70+
EOF
71+
)
72+
73+
print_section "github context" "$github_context_body"
74+
print_section "matrix context" "$(format_value "$MATRIX_CONTEXT")"
75+
print_section "job context" "$(format_value "$JOB_CONTEXT")"
76+
print_section "runner context" "$(format_value "$RUNNER_CONTEXT")"
77+
print_section "caller inputs" "$(format_value "$CALLER_INPUTS")"
78+
print_section "caller needs" "$(format_value "$CALLER_NEEDS")"
79+
print_section "caller vars" "$(format_value "$CALLER_VARS")"
80+
print_section "extras" "$(format_value "$EXTRAS")"
81+
82+
exit 0
83+
fi

action.yml

Lines changed: 9 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
name: Print Workflow Data
2-
description: "prints select github context for debugging purposes"
2+
description: 'prints select github context for debugging purposes'
33

44
branding:
55
color: 'green'
66
icon: 'bar-chart-2'
77

88
inputs:
99
caller-inputs:
10-
description: '`caller-inputs: {{ toJSON(inputs) }}`'
10+
description: '`caller-inputs: ${{ toJSON(inputs) }}`'
1111
required: false
1212
default: ''
1313
caller-needs:
14-
description: '`caller-needs: {{ toJSON(needs) }}`'
14+
description: '`caller-needs: ${{ toJSON(needs) }}`'
1515
required: false
1616
default: ''
1717
caller-vars:
18-
description: 'pass via `caller-vars: {{ toJSON(vars) }}` (generally safe unless secrets have been mismanaged)'
18+
description: 'pass via `caller-vars: ${{ toJSON(vars) }}` (generally safe unless secrets have been mismanaged)'
1919
required: false
2020
default: ''
2121
extras:
@@ -24,57 +24,20 @@ inputs:
2424
default: ''
2525

2626
runs:
27-
using: "composite"
27+
using: 'composite'
2828
steps:
2929
- name: Print Workflow Data
3030
shell: bash
3131
continue-on-error: true
3232
env:
33+
TRIGGERING_ACTOR: ${{ github.triggering_actor }}
34+
EVENT_ACTION: ${{ github.event.action }}
35+
DEFAULT_BRANCH: ${{ github.event && github.event.repository && github.event.repository.default_branch }}
3336
MATRIX_CONTEXT: ${{ matrix && toJSON(matrix) || 'n/a' }}
3437
JOB_CONTEXT: ${{ toJSON(job) }}
3538
RUNNER_CONTEXT: ${{ toJSON(runner) }}
3639
CALLER_INPUTS: ${{ inputs.caller-inputs != '' && inputs.caller-inputs || 'n/a' }}
3740
CALLER_NEEDS: ${{ inputs.caller-needs != '' && inputs.caller-needs || 'n/a' }}
3841
CALLER_VARS: ${{ inputs.caller-vars != '' && inputs.caller-vars || 'n/a' }}
3942
EXTRAS: ${{ inputs.extras != '' && inputs.extras || 'n/a' }}
40-
DEFAULT_BRANCH: ${{ github.event && github.event.repository && github.event.repository.default_branch }}
41-
run: |
42-
print_section() {
43-
local title="$1"
44-
local body="$2"
45-
local color=92 # bright green
46-
local bar_len=$(( ${#title} + 2 ))
47-
echo -e "\e[1;${color}m┌$(printf '─%.0s' $(seq 1 $bar_len))┐\e[0m"
48-
echo -e "\e[1;${color}m│ ${title} │\e[0m"
49-
echo -e "\e[1;${color}m└$(printf '─%.0s' $(seq 1 $bar_len))┘\e[0m"
50-
echo -e "$body"
51-
}
52-
53-
github_context_body=$(cat <<EOF
54-
github.actor : ${{ github.actor }}
55-
github.triggering_actor : ${{ github.triggering_actor }}
56-
github.workflow : ${{ github.workflow }}
57-
github.workflow_ref : ${{ github.workflow_ref }}
58-
github.run_id : ${{ github.run_id }}
59-
github.run_number : ${{ github.run_number }}
60-
github.run_attempt : ${{ github.run_attempt }}
61-
github.event_name : ${{ github.event_name }}
62-
github.event.action : ${{ github.event.action }}
63-
github.base_ref : ${{ github.base_ref }}
64-
github.head_ref : ${{ github.head_ref }}
65-
is_default_branch : ${{ github.ref_name == env.DEFAULT_BRANCH }}
66-
is_default_target : ${{ github.base_ref == env.DEFAULT_BRANCH }}
67-
github.ref : ${{ github.ref }}
68-
github.ref_name : ${{ github.ref_name }}
69-
github.sha : ${{ github.sha }}
70-
EOF
71-
)
72-
73-
print_section "github context" "$github_context_body"
74-
print_section "matrix context" "$MATRIX_CONTEXT"
75-
print_section "job context" "$JOB_CONTEXT"
76-
print_section "runner context" "$RUNNER_CONTEXT"
77-
print_section "caller inputs" "$CALLER_INPUTS"
78-
print_section "caller needs" "$CALLER_NEEDS"
79-
print_section "caller vars" "$CALLER_VARS"
80-
print_section "extras" "$EXTRAS"
43+
run: ${{ github.action_path }}/action.sh

0 commit comments

Comments
 (0)