22name : SDK Diff Analyzer
33
44# Analyzes gdc-nas repository for REST API changes that may require SDK updates.
5+ # Uses GitHub API - no clone required.
56# Reports are uploaded as artifacts for use by sdk-analyze and jira-sync skills.
67
78on :
1314 workflow_dispatch :
1415 inputs :
1516 commits_to_analyze :
16- description : ' Number of commits to analyze if no state exists (default: 50)'
17+ description : ' Number of commits to analyze (default: 50)'
1718 default : ' 50'
18- force_full_scan :
19- description : ' Ignore last-analyzed state and analyze N commits from HEAD'
20- default : ' false'
21- type : boolean
19+ since_commit :
20+ description : ' Analyze since this commit SHA (overrides state tag)'
21+ default : ' '
2222 debug :
2323 description : ' Enable verbose debug logging'
2424 default : ' true'
2525 type : boolean
2626
2727env :
28- # Tag in this repo that stores the last analyzed gdc-nas commit hash
29- STATE_TAG : ' gdc-nas-analyzer/last-commit'
3028 GDC_NAS_REPO : ' gooddata/gdc-nas'
29+ # File in this repo that stores the last analyzed gdc-nas commit SHA
30+ STATE_FILE : ' .github/gdc-nas-last-analyzed.txt'
3131
3232jobs :
3333 analyze :
@@ -37,206 +37,115 @@ jobs:
3737 permissions :
3838 contents : write
3939 actions : write
40+ env :
41+ # Use PAT for gdc-nas access, falls back to GITHUB_TOKEN
42+ GH_TOKEN : ${{ secrets.GDC_NAS_READ_TOKEN || secrets.GITHUB_TOKEN }}
4043 steps :
41- - name : Debug - Show environment
44+ - name : Debug - Environment info
4245 run : |
43- echo "=== Environment Info ==="
46+ echo "=== Environment ==="
4447 echo "Repository: ${{ github.repository }}"
45- echo "Ref: ${{ github.ref }}"
46- echo "SHA: ${{ github.sha }}"
47- echo "Actor: ${{ github.actor }}"
4848 echo "Event: ${{ github.event_name }}"
49- echo "Runner OS : ${{ runner.os }}"
50- echo "Working directory : $(pwd )"
49+ echo "Runner: ${{ runner.os }}"
50+ echo "GH CLI version : $(gh --version | head -1 )"
5151 echo ""
5252 echo "=== Inputs ==="
5353 echo "commits_to_analyze: ${{ inputs.commits_to_analyze || '50' }}"
54- echo "force_full_scan: ${{ inputs.force_full_scan || 'false' }}"
55- echo "debug: ${{ inputs.debug || 'true' }}"
56-
57- - name : Checkout SDK repository
58- uses : actions/checkout@v4
59- with :
60- fetch-depth : 0 # Need full history for tag operations
54+ echo "since_commit: ${{ inputs.since_commit || '(not set)' }}"
6155
62- - name : Debug - SDK repo info
56+ - name : Verify gdc-nas access
6357 run : |
64- echo "=== SDK Repository ==="
65- echo "Current directory: $(pwd)"
66- echo "Git status:"
67- git status
68- echo ""
69- echo "Recent tags:"
70- git tag -l | tail -10 || echo "No tags found"
71- echo ""
72- echo "Looking for state tag '${{ env.STATE_TAG }}':"
73- git show-ref --tags "${{ env.STATE_TAG }}" || echo "State tag not found"
58+ echo "=== Testing API access to ${{ env.GDC_NAS_REPO }} ==="
59+ if gh api "repos/${{ env.GDC_NAS_REPO }}" --jq '.full_name' 2>/dev/null; then
60+ echo "✅ Access verified"
61+ else
62+ echo "❌ Cannot access ${{ env.GDC_NAS_REPO }}"
63+ echo ""
64+ echo "To fix: Add a Personal Access Token with 'repo' scope as secret GDC_NAS_READ_TOKEN"
65+ exit 1
66+ fi
7467
75- - name : Clone gdc-nas repository
68+ - name : Checkout SDK repository
7669 uses : actions/checkout@v4
7770 with :
78- repository : ${{ env.GDC_NAS_REPO }}
79- path : gdc-nas
80- fetch-depth : 0 # Full history needed for diff analysis
81- token : ${{ secrets.GDC_NAS_READ_TOKEN || secrets.GITHUB_TOKEN }}
82-
83- - name : Debug - gdc-nas repo info
84- run : |
85- echo "=== gdc-nas Repository ==="
86- echo "Directory contents:"
87- ls -la gdc-nas/ | head -20
88- echo ""
89- echo "Git log (last 5 commits):"
90- git -C gdc-nas log --oneline -5
91- echo ""
92- echo "Current HEAD:"
93- git -C gdc-nas rev-parse HEAD
94- echo ""
95- echo "Total commits in repo:"
96- git -C gdc-nas rev-list --count HEAD
71+ fetch-depth : 1
9772
9873 - name : Setup Python
9974 uses : actions/setup-python@v5
10075 with :
10176 python-version : ' 3.12'
10277
103- - name : Debug - Python info
78+ - name : Get current gdc-nas HEAD
79+ id : gdc_nas
10480 run : |
105- echo "=== Python Environment ==="
106- python3 --version
107- which python3
108- echo ""
109- echo "Analyzer script exists:"
110- ls -la scripts/gdc_nas_diff_analyzer.py || echo "SCRIPT NOT FOUND!"
111- echo ""
112- echo "Script is executable:"
113- head -5 scripts/gdc_nas_diff_analyzer.py
81+ HEAD_SHA=$(gh api "repos/${{ env.GDC_NAS_REPO }}/commits/HEAD" --jq '.sha')
82+ echo "head_sha=$HEAD_SHA" >> $GITHUB_OUTPUT
83+ echo "gdc-nas HEAD: $HEAD_SHA"
11484
115- - name : Get last analyzed commit
116- id : state
85+ - name : Determine analysis range
86+ id : range
11787 run : |
118- set -x # Enable command tracing
119-
120- COMMITS_TO_ANALYZE="${{ inputs.commits_to_analyze || '50' }}"
121- FORCE_FULL="${{ inputs.force_full_scan || 'false' }}"
122-
123- echo "=== Determining analysis range ==="
124- echo "COMMITS_TO_ANALYZE: $COMMITS_TO_ANALYZE"
125- echo "FORCE_FULL: $FORCE_FULL"
126-
127- # Get current gdc-nas HEAD
128- GDC_NAS_HEAD=$(git -C gdc-nas rev-parse HEAD)
129- echo "gdc_nas_head=$GDC_NAS_HEAD" >> $GITHUB_OUTPUT
130- echo "Current gdc-nas HEAD: $GDC_NAS_HEAD"
131-
132- if [ "$FORCE_FULL" = "true" ]; then
133- echo "Force full scan requested"
134- echo "since=HEAD~${COMMITS_TO_ANALYZE}" >> $GITHUB_OUTPUT
135- echo "mode=force" >> $GITHUB_OUTPUT
136- elif git show-ref --tags --quiet "$STATE_TAG"; then
137- # Tag exists - get the stored gdc-nas commit from tag message
138- echo "State tag found, reading contents..."
139- LAST_COMMIT=$(git tag -l --format='%(contents)' "$STATE_TAG" | head -1)
140- echo "Found state tag with gdc-nas commit: $LAST_COMMIT"
141-
142- # Verify this commit exists in gdc-nas
143- if git -C gdc-nas rev-parse "$LAST_COMMIT" >/dev/null 2>&1; then
144- echo "Commit verified in gdc-nas"
145- echo "since=$LAST_COMMIT" >> $GITHUB_OUTPUT
88+ COMMITS="${{ inputs.commits_to_analyze || '50' }}"
89+ SINCE_INPUT="${{ inputs.since_commit }}"
90+
91+ echo "=== Determining range ==="
92+
93+ if [ -n "$SINCE_INPUT" ]; then
94+ # User provided explicit since commit
95+ echo "Using user-provided since commit: $SINCE_INPUT"
96+ echo "since=$SINCE_INPUT" >> $GITHUB_OUTPUT
97+ echo "mode=manual" >> $GITHUB_OUTPUT
98+ elif [ -f "${{ env.STATE_FILE }}" ]; then
99+ # Read from state file
100+ LAST_SHA=$(cat "${{ env.STATE_FILE }}" | tr -d '[:space:]')
101+ echo "Found state file with SHA: $LAST_SHA"
102+
103+ # Verify commit exists
104+ if gh api "repos/${{ env.GDC_NAS_REPO }}/commits/$LAST_SHA" --jq '.sha' >/dev/null 2>&1; then
105+ echo "Commit verified, using incremental mode"
106+ echo "since=$LAST_SHA" >> $GITHUB_OUTPUT
146107 echo "mode=incremental" >> $GITHUB_OUTPUT
147108 else
148- echo "Warning: Stored commit not found in gdc-nas , falling back to HEAD~${COMMITS_TO_ANALYZE} "
149- echo "since=HEAD~${COMMITS_TO_ANALYZE} " >> $GITHUB_OUTPUT
109+ echo "Stored commit not found, falling back to last $COMMITS commits "
110+ echo "since=" >> $GITHUB_OUTPUT
150111 echo "mode=fallback" >> $GITHUB_OUTPUT
112+ echo "commits=$COMMITS" >> $GITHUB_OUTPUT
151113 fi
152114 else
153- echo "No state tag found , analyzing last ${COMMITS_TO_ANALYZE} commits"
154- echo "since=HEAD~${COMMITS_TO_ANALYZE} " >> $GITHUB_OUTPUT
115+ echo "No state file , analyzing last $COMMITS commits"
116+ echo "since=" >> $GITHUB_OUTPUT
155117 echo "mode=initial" >> $GITHUB_OUTPUT
118+ echo "commits=$COMMITS" >> $GITHUB_OUTPUT
156119 fi
157120
158- set +x
159-
160- - name : Check for new commits
161- id : check
162- working-directory : gdc-nas
121+ - name : Run API-based analyzer
122+ id : analyze
163123 run : |
164- set -x
165- SINCE="${{ steps.state.outputs.since }}"
166-
167- echo "=== Checking commits ==="
168- echo "SINCE: $SINCE"
124+ mkdir -p reports
169125
170- # Count commits to analyze
171- if [[ "$SINCE" == HEAD~* ]]; then
172- NUM="${SINCE#HEAD~}"
173- COMMIT_COUNT=$NUM
174- echo "Using HEAD~N format, will analyze $NUM commits"
175- else
176- COMMIT_COUNT=$(git rev-list --count "${SINCE}..HEAD" 2>/dev/null || echo "0")
177- echo "Counting commits from $SINCE to HEAD: $COMMIT_COUNT"
178- fi
126+ echo "=== Running Analyzer ==="
127+ echo "Mode: ${{ steps.range.outputs.mode }}"
179128
180- echo "commit_count=$COMMIT_COUNT" >> $GITHUB_OUTPUT
129+ ARGS="--repo ${{ env.GDC_NAS_REPO }} --output-dir ./reports"
181130
182- if [ "$COMMIT_COUNT" -eq 0 ]; then
183- echo "No new commits to analyze"
184- echo "skip=true" >> $GITHUB_OUTPUT
131+ if [ -n "${{ steps.range.outputs.since }}" ]; then
132+ ARGS="$ARGS --since ${{ steps.range.outputs.since }}"
185133 else
186- echo "Will analyze $COMMIT_COUNT commits"
187- echo "skip=false" >> $GITHUB_OUTPUT
134+ ARGS="$ARGS --commits ${{ steps.range.outputs.commits || '50' }}"
188135 fi
189- set +x
190-
191- - name : Run SDK diff analyzer
192- if : steps.check.outputs.skip != 'true'
193- run : |
194- set -x
195- mkdir -p reports
196-
197- echo "=== Running Analyzer ==="
198- echo "Since: ${{ steps.state.outputs.since }}"
199- echo "Mode: ${{ steps.state.outputs.mode }}"
200- echo "Commit count: ${{ steps.check.outputs.commit_count }}"
201-
202- # Run with verbose output
203- python3 scripts/gdc_nas_diff_analyzer.py \
204- --since "${{ steps.state.outputs.since }}" \
205- --sdk-details \
206- --output-dir ./reports \
207- --repo-path ./gdc-nas \
208- 2>&1 | tee analyzer_output.log
209136
210- ANALYZER_EXIT_CODE=${PIPESTATUS[0]}
211- echo "Analyzer exit code: $ANALYZER_EXIT_CODE"
137+ echo "Running: python3 scripts/gdc_nas_api_analyzer.py $ARGS"
138+ python3 scripts/gdc_nas_api_analyzer.py $ARGS 2>&1 | tee analyzer.log
212139
213140 echo ""
214- echo "=== Reports directory ==="
215- ls -la reports/ || echo "Reports directory empty or missing"
141+ echo "=== Reports ==="
142+ ls -la reports/
216143
217- # Check if any reports were generated
218- if [ -f reports/00-summary.md ]; then
219- echo ""
220- echo "=== Summary report content ==="
221- cat reports/00-summary.md
222- else
223- echo "No SDK-relevant changes detected, creating minimal summary"
224- cat > reports/00-summary.md << EOF
225- # SDK Diff Analysis - No Changes
226-
227- **Run:** ${{ github.run_number }}
228- **Date:** $(date -u +%Y-%m-%dT%H:%M:%SZ)
229- **Mode:** ${{ steps.state.outputs.mode }}
230- **Commits analyzed:** ${{ steps.check.outputs.commit_count }}
231- **gdc-nas HEAD:** \`${{ steps.state.outputs.gdc_nas_head }}\`
232-
233- *No SDK-relevant changes detected in the analyzed commits.*
234- EOF
235- fi
236- set +x
144+ # Count SDK-relevant reports (excluding summary)
145+ REPORT_COUNT=$(ls reports/*.md 2>/dev/null | grep -v "00-summary" | wc -l || echo "0")
146+ echo "sdk_reports=$REPORT_COUNT" >> $GITHUB_OUTPUT
237147
238148 - name : Upload analysis reports
239- if : steps.check.outputs.skip != 'true'
240149 uses : actions/upload-artifact@v4
241150 with :
242151 name : sdk-diff-reports-${{ github.run_number }}
@@ -248,49 +157,44 @@ jobs:
248157 uses : actions/upload-artifact@v4
249158 with :
250159 name : analyzer-log-${{ github.run_number }}
251- path : analyzer_output .log
160+ path : analyzer .log
252161 retention-days : 7
253162 if-no-files-found : ignore
254163
255- - name : Update state tag
256- if : steps.check.outputs.skip != 'true'
164+ - name : Update state file
257165 run : |
258- set -x
259- GDC_NAS_HEAD ="${{ steps.state .outputs.gdc_nas_head }}"
166+ echo "=== Updating state ==="
167+ HEAD_SHA ="${{ steps.gdc_nas .outputs.head_sha }}"
260168
261- echo "=== Updating state tag === "
262- echo "Will store gdc-nas commit : $GDC_NAS_HEAD "
169+ echo "$HEAD_SHA" > "${{ env.STATE_FILE }} "
170+ echo "Stored SHA : $HEAD_SHA "
263171
264- # Configure git for tagging
172+ # Commit and push state file
265173 git config user.name "github-actions[bot]"
266174 git config user.email "github-actions[bot]@users.noreply.github.com"
267175
268- # Create/update annotated tag with gdc-nas commit in message
269- git tag -f -a "$STATE_TAG" -m "$GDC_NAS_HEAD"
270-
271- echo "Pushing tag to origin..."
272- git push -f origin "$STATE_TAG"
273-
274- echo "Updated $STATE_TAG to track gdc-nas commit: $GDC_NAS_HEAD"
176+ git add "${{ env.STATE_FILE }}"
275177
276- # Verify
277- echo "Verifying tag:"
278- git show-ref --tags "$STATE_TAG"
279- set +x
178+ if git diff --staged --quiet; then
179+ echo "No changes to state file"
180+ else
181+ git commit -m "chore: update gdc-nas analyzer state to ${HEAD_SHA:0:12}"
182+ git push
183+ echo "State file updated and pushed"
184+ fi
280185
281186 - name : Job summary
282187 if : always()
283188 run : |
284- cat >> $GITHUB_STEP_SUMMARY << EOF
189+ cat >> $GITHUB_STEP_SUMMARY << ' EOF'
285190 ## SDK Diff Analyzer Results
286191
287192 | Parameter | Value |
288193 |-----------|-------|
289- | Mode | ${{ steps.state.outputs.mode }} |
290- | Since | \`${{ steps.state.outputs.since }}\` |
291- | gdc-nas HEAD | \`${{ steps.state.outputs.gdc_nas_head }}\` |
292- | Commits analyzed | ${{ steps.check.outputs.commit_count }} |
293- | Skipped | ${{ steps.check.outputs.skip }} |
194+ | Mode | ${{ steps.range.outputs.mode }} |
195+ | Since | `${{ steps.range.outputs.since || 'N/A' }}` |
196+ | gdc-nas HEAD | `${{ steps.gdc_nas.outputs.head_sha }}` |
197+ | SDK-relevant commits | ${{ steps.analyze.outputs.sdk_reports }} |
294198
295199 EOF
296200
0 commit comments