Skip to content

Commit f66b7dc

Browse files
committed
added determine-package action
1 parent b46c17e commit f66b7dc

1 file changed

Lines changed: 178 additions & 0 deletions

File tree

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
name: 'Determine Packages to Publish'
2+
description: 'Determines which packages need publishing based on event type and changes.'
3+
4+
inputs:
5+
event_name:
6+
description: 'The name of the event that triggered the workflow (github.event_name)'
7+
required: true
8+
dispatch_package_input:
9+
description: 'The package input from workflow_dispatch (github.event.inputs.package)'
10+
required: false
11+
default: ''
12+
# Configuration for packages and their paths
13+
# Expected format (YAML string):
14+
# packages:
15+
# framework:
16+
# paths:
17+
# - 'packages/framework/**'
18+
# eslint-plugin:
19+
# paths:
20+
# - 'packages/eslint-plugin/**'
21+
# common_paths: # Optional: paths that trigger ALL packages if changed
22+
# - '.github/workflows/continuous-delivery.yml'
23+
# - '.github/workflows/reusable-continuous-delivery.yml'
24+
packages_config:
25+
description: 'YAML string defining packages and their trigger paths.'
26+
required: true
27+
28+
outputs:
29+
packages_json:
30+
description: 'JSON string array of package names to be published, e.g., ["framework", "eslint-plugin"]. Empty array [] if none.'
31+
value: ${{ steps.set-matrix.outputs.packages_json }}
32+
33+
runs:
34+
using: "composite"
35+
steps:
36+
# 0. Setup - Install dependencies (yq)
37+
- name: Install yq
38+
shell: bash
39+
run: |
40+
echo "::group::Install yq"
41+
if ! command -v yq &> /dev/null
42+
then
43+
echo "yq not found. Installing..."
44+
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
45+
echo "yq installed successfully to $(command -v yq)"
46+
else
47+
echo "yq already installed at $(command -v yq)"
48+
fi
49+
echo "::endgroup::"
50+
51+
# 1. Handle workflow_dispatch trigger
52+
- name: Check Dispatch Input
53+
id: check-dispatch
54+
if: inputs.event_name == 'workflow_dispatch'
55+
shell: bash
56+
run: |
57+
pkg_input="${{ inputs.dispatch_package_input }}"
58+
packages_config_yaml='${{ inputs.packages_config }}'
59+
# Extract all package names from the config
60+
all_packages=$(echo "$packages_config_yaml" | yq '[.packages | keys] | @json')
61+
62+
if [[ -z "$pkg_input" ]]; then
63+
# Dispatch trigger with no specific package -> run all defined packages
64+
echo "packages_json=${all_packages}" >> $GITHUB_OUTPUT
65+
else
66+
# Dispatch trigger with specific package -> run only that one
67+
# Validate if the input package exists in config
68+
exists=$(echo "$packages_config_yaml" | yq ".packages.${pkg_input}")
69+
if [[ "$exists" != "null" ]]; then
70+
echo "packages_json=[\"$pkg_input\"]" >> $GITHUB_OUTPUT
71+
else
72+
echo "Warning: Dispatched package '$pkg_input' not found in configuration. Outputting empty list."
73+
echo "packages_json=[]" >> $GITHUB_OUTPUT
74+
fi
75+
fi
76+
# Install yq for YAML parsing (needs to be done only once if runner reused)
77+
# echo "::add-matcher::${{ runner.tool_cache }}/yq.json"
78+
# sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
79+
80+
# 2. Handle push trigger
81+
- name: Checkout Code (Push Only)
82+
# Only checkout if push event, as paths-filter needs the code
83+
if: inputs.event_name == 'push'
84+
uses: actions/checkout@v4
85+
with:
86+
fetch-depth: 0 # Needed for paths-filter comparison
87+
88+
- name: Generate Paths Filter Config (Push Only)
89+
id: generate-filter
90+
if: inputs.event_name == 'push'
91+
shell: bash
92+
run: |
93+
packages_config_yaml='${{ inputs.packages_config }}'
94+
common_paths_yaml=$(echo "$packages_config_yaml" | yq '.common_paths | map_values(.') # Convert common_paths list to YAML list string
95+
# If common_paths is null or empty, set to empty string for concatenation
96+
if [[ "$common_paths_yaml" == "null" || "$common_paths_yaml" == "[]" ]]; then
97+
common_paths_yaml=""
98+
fi
99+
100+
filter_yaml=""
101+
# Extract package names
102+
package_names=$(echo "$packages_config_yaml" | yq '[.packages | keys] | .[]')
103+
104+
for pkg in $package_names; do
105+
# Get specific paths for the package
106+
pkg_paths_yaml=$(echo "$packages_config_yaml" | yq ".packages.${pkg}.paths | map_values(.')")
107+
# Start building the filter entry for this package
108+
filter_yaml+="${pkg}:\\\\n"
109+
# Indent and add package-specific paths
110+
indented_pkg_paths=$(echo "$pkg_paths_yaml" | sed 's/^/ /')
111+
filter_yaml+="${indented_pkg_paths}\\\\n"
112+
# Indent and add common paths (if any)
113+
if [[ -n "$common_paths_yaml" ]]; then
114+
indented_common_paths=$(echo "$common_paths_yaml" | sed 's/^/ /')
115+
filter_yaml+="${indented_common_paths}\\\\n"
116+
fi
117+
done
118+
119+
# Escape newlines for multiline output
120+
filter_yaml=$(echo -e "$filter_yaml")
121+
echo "filters<<EOF" >> $GITHUB_OUTPUT
122+
echo "$filter_yaml" >> $GITHUB_OUTPUT
123+
echo "EOF" >> $GITHUB_OUTPUT
124+
# Install yq for YAML parsing (needs to be done only once if runner reused)
125+
# echo "::add-matcher::${{ runner.tool_cache }}/yq.json"
126+
# sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
127+
128+
- name: Filter Paths (Push Only)
129+
id: changes
130+
if: inputs.event_name == 'push'
131+
uses: dorny/paths-filter@v3
132+
with:
133+
filters: ${{ steps.generate-filter.outputs.filters }}
134+
135+
- name: Set Matrix based on Changes (Push Only)
136+
id: set-matrix-push
137+
if: inputs.event_name == 'push'
138+
shell: bash
139+
run: |
140+
packages_config_yaml='${{ inputs.packages_config }}'
141+
declare -a packages
142+
# Extract package names
143+
package_names=$(echo "$packages_config_yaml" | yq '[.packages | keys] | .[]')
144+
145+
for pkg in $package_names; do
146+
# Check the output of the paths-filter step for this package
147+
# Simplified check using direct context access
148+
if [[ "${{ steps.changes.outputs.${pkg} }}" == "true" ]]; then
149+
packages+=("\"$pkg\"") # Add package name with quotes
150+
fi
151+
done
152+
153+
# Join array elements with comma, wrap in brackets for JSON
154+
# Works even if array is empty (produces '[]')
155+
packages_json=$(printf ',%s' "${packages[@]}")
156+
packages_json="[${packages_json:1}]"
157+
158+
echo "packages_json=${packages_json}" >> $GITHUB_OUTPUT
159+
# Install yq for YAML parsing (needs to be done only once if runner reused)
160+
# echo "::add-matcher::${{ runner.tool_cache }}/yq.json"
161+
# sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
162+
163+
# 3. Finalize Matrix Output
164+
- name: Finalize Matrix Output
165+
id: set-matrix # This step sets the final action output
166+
shell: bash
167+
run: |
168+
packages_json="[]" # Default empty array
169+
if [[ "${{ inputs.event_name }}" == "workflow_dispatch" ]]; then
170+
packages_json='${{ steps.check-dispatch.outputs.packages_json }}'
171+
elif [[ "${{ inputs.event_name }}" == "push" ]]; then
172+
packages_json='${{ steps.set-matrix-push.outputs.packages_json }}'
173+
fi
174+
# Ensure output is valid JSON array even if intermediate steps failed/produced empty output
175+
if [[ -z $packages_json ]]; then
176+
packages_json="[]"
177+
fi
178+
echo "packages_json=${packages_json}" >> $GITHUB_OUTPUT

0 commit comments

Comments
 (0)