66 - main # Trigger on push to main branch
77 tags :
88 - ' v*.*.*' # Trigger on push of version tags (e.g., v0.5.5)
9- pull_request : # Added PR trigger
9+ pull_request :
1010 branches :
11- - main
12-
13- # Prevent concurrent runs for the same PR or branch
14- concurrency :
15- group : ${{ github.workflow }}-${{ github.ref }}
16- cancel-in-progress : true
11+ - main # Trigger on PR to main branch
1712
1813jobs :
19- validate : # New validation job
20- name : Validate Code
14+ validate :
15+ name : Validate Code Quality
2116 runs-on : ubuntu-latest
17+ permissions : # Added permissions
18+ actions : read
19+ contents : read
20+ security-events : write # Required for CodeQL results
2221 steps :
2322 - name : Checkout repository
24- uses : actions/checkout@v4.1.7 # Specific version
23+ uses : actions/checkout@v4.1.7
24+
25+ # Initializes the CodeQL tools for scanning. # Added CodeQL init
26+ - name : Initialize CodeQL
27+ uses : github/codeql-action/init@v3
28+ with :
29+ languages : typescript # Specify the language to analyze
30+ # Optional: config-file: './.github/codeql/codeql-config.yml'
31+ # Optional: queries: '+security-extended'
32+
33+ - name : Install pnpm
34+ uses : pnpm/action-setup@v4
35+ with :
36+ version : latest # Use the latest pnpm version
2537
2638 - name : Set up Node.js
27- uses : actions/setup-node@v4.0.3 # Specific version
39+ uses : actions/setup-node@v4.0.3
2840 with :
29- node-version : ' 22 ' # Use latest LTS
30- cache : ' pnpm' # Use pnpm cache
41+ node-version : ' lts/* ' # Use latest LTS
42+ cache : ' pnpm' # Let pnpm handle caching via pnpm/action-setup
3143
32- - name : Install pnpm globally
33- run : npm install -g pnpm
44+ - name : Install dependencies # Correct install step
45+ run : pnpm install --frozen-lockfile
3446
35- - name : Install dependencies
36- run : pnpm install --frozen-lockfile # Use pnpm install
47+ - name : Check for vulnerabilities # Added pnpm audit
48+ run : pnpm audit --prod # Check only production dependencies
3749
38- - name : Check formatting
39- run : pnpm run check-format
50+ - name : Check Formatting
51+ run : pnpm run check-format # Fails job if check fails
4052
41- - name : Lint code
42- run : pnpm run lint
53+ - name : Lint Code
54+ run : pnpm run lint # Fails job if lint fails
4355
44- - name : Perform type checking
45- run : pnpm run typecheck
56+ - name : Run Tests and Check Coverage
57+ run : pnpm run test:cov # Fails job if tests fail or coverage threshold not met
4658
47- - name : Run tests with coverage
48- run : pnpm run test:cov
59+ - name : Upload coverage to Codecov
60+ uses : codecov/codecov-action@v4.5.0 # Use Codecov action with fixed version
61+ with :
62+ token : ${{ secrets.CODECOV_TOKEN }} # Use Codecov token
63+ files : ./coverage/lcov.info # Specify LCOV file path
64+ fail_ci_if_error : true # Optional: fail CI if upload error
65+
66+ - name : Upload test results to Codecov
67+ if : ${{ !cancelled() }}
68+ uses : codecov/test-results-action@v1
69+ with :
70+ token : ${{ secrets.CODECOV_TOKEN }}
71+ # No file specified, action defaults to common patterns like test-report.junit.xml
72+
73+ - name : Perform CodeQL Analysis # Added CodeQL analyze
74+ uses : github/codeql-action/analyze@v3
4975
50- - name : Upload coverage to Coveralls
51- uses : coverallsapp/github-action@v2.3.0 # Specific version
76+ - name : Upload coverage reports # Kept artifact upload
77+ uses : actions/upload-artifact@v4.4.0
5278 with :
53- github-token : ${{ secrets.GITHUB_TOKEN }}
54- path-to-lcov : ./coverage/lcov.info # Verify path exists after test:cov
55- flag-name : run-${{ matrix.node-version || 'node-22' }} # Use matrix or default (updated node version)
56- parallel : false # Set to true if using parallel matrix later
79+ name : coverage-report
80+ path : coverage/ # Upload the whole coverage directory
5781
58- build :
59- needs : validate # Depends on validation passing
82+ build-archive :
83+ name : Build and Archive Artifacts
84+ needs : validate # Depends on successful validation
6085 runs-on : ubuntu-latest
61- outputs :
86+ if : startsWith(github.ref, 'refs/tags/v') # Only run for tags
87+ outputs : # Define outputs for the release job
6288 version : ${{ steps.get_version.outputs.version }}
63- artifact_name : build-artifacts-archive # Consistent name for upload/download
64- archive_filename : ${{ steps.archive_build.outputs.archive_name }} # Actual .tar.gz filename
89+ artifact_path : ${{ steps.archive_build.outputs.artifact_path }}
90+ # Removed incorrect permissions block from here
6591 steps :
6692 - name : Checkout repository
67- uses : actions/checkout@v4.1.7 # Specific version
93+ uses : actions/checkout@v4.1.7
94+ # Removed incorrect CodeQL init from here
6895
69- - name : Set up Node.js
70- uses : actions/setup-node @v4.0.3 # Specific version
96+ - name : Install pnpm
97+ uses : pnpm/action-setup @v4
7198 with :
72- node-version : ' 22' # Use latest LTS
73- cache : ' pnpm' # Use pnpm cache
99+ version : latest
74100
75- - name : Install pnpm globally
76- run : npm install -g pnpm
101+ - name : Set up Node.js
102+ uses : actions/setup-node@v4.0.3
103+ with :
104+ node-version : ' lts/*' # Use latest LTS
105+ registry-url : ' https://registry.npmjs.org/' # For pnpm publish
106+ cache : ' pnpm' # Let pnpm handle caching
77107
78108 - name : Install dependencies
79- run : pnpm install --frozen-lockfile # Use pnpm install
109+ run : pnpm install --frozen-lockfile
80110
81111 - name : Build project
82112 run : pnpm run build
83113
84- - name : Get package version
114+ - name : Get package version from tag
85115 id : get_version
86116 run : |
87- VERSION=""
88- if [[ "${{ github.ref_type }}" == "tag" && "${{ github.ref }}" == refs/tags/v* ]]; then
89- VERSION=$(echo "${{ github.ref }}" | sed 's#refs/tags/##')
90- else
91- VERSION=$(node -p "require('./package.json').version")
92- fi
117+ VERSION=$(echo "${{ github.ref }}" | sed 's#refs/tags/##')
93118 echo "version=$VERSION" >> $GITHUB_OUTPUT
94119
95- # --- Conditional Artifact Archiving and Upload ---
96- - name : Archive build artifacts (only on tag push)
97- if : startsWith(github.ref, 'refs/tags/v') # Condition: Only run for tags
120+ - name : Archive build artifacts for release
98121 id : archive_build
99122 run : |
100- # Ensure scripts directory is included if postbuild.js is needed
101- tar -czf build-artifacts.tar.gz build package.json pnpm-lock.yaml README.md CHANGELOG.md LICENSE Dockerfile .dockerignore scripts/postbuild.js # Replaced package-lock with pnpm-lock
102- echo "archive_name=build-artifacts.tar.gz " >> $GITHUB_OUTPUT
123+ ARTIFACT_NAME="pdf-reader-mcp-${{ steps.get_version.outputs.version }}.tar.gz"
124+ tar -czf $ARTIFACT_NAME dist package.json README.md LICENSE CHANGELOG.md
125+ echo "artifact_path=$ARTIFACT_NAME " >> $GITHUB_OUTPUT
103126
104- - name : Upload build artifacts (only on tag push)
105- if : startsWith(github.ref, 'refs/tags/v') # Condition: Only run for tags
106- uses : actions/upload-artifact@v4.3.4 # Specific version
127+ - name : Upload build artifact for release job
128+ uses : actions/upload-artifact@v4.4.0
107129 with :
108- name : build-artifacts-archive # Use consistent name
109- path : ${{ steps.archive_build.outputs.archive_name }}
130+ name : release-artifact
131+ path : ${{ steps.archive_build.outputs.artifact_path }}
132+
133+ # Publish steps moved to parallel jobs below
110134
111135 publish-npm :
112- needs : [validate, build] # Depends on validate and build
136+ name : Publish to NPM
137+ needs : build-archive # Depends on build-archive completion
113138 runs-on : ubuntu-latest
114- if : startsWith(github.ref, 'refs/tags/v') # Condition: Only run for tags
115- permissions : # Added permissions for trusted publishing (recommended)
116- contents : read
117- id-token : write
139+ if : startsWith(github.ref, 'refs/tags/v') # Only run for tags
118140 steps :
119- - name : Download build artifacts archive
120- uses : actions/download-artifact@v4.1.8 # Specific version
121- with :
122- name : ${{ needs.build.outputs.artifact_name }} # Use consistent artifact name
123- path : .
141+ - name : Checkout repository
142+ uses : actions/checkout@v4.1.7
124143
125- - name : Extract build artifacts
126- run : tar -xzf build-artifacts.tar.gz # Use the correct archive filename
144+ - name : Install pnpm
145+ uses : pnpm/action-setup@v4
146+ with :
147+ version : latest
127148
128- - name : Set up Node.js for npm publish
129- uses : actions/setup-node@v4.0.3 # Specific version
149+ - name : Set up Node.js for NPM
150+ uses : actions/setup-node@v4.0.3
130151 with :
131- node-version : ' 22 ' # Use latest LTS
152+ node-version : ' lts/* '
132153 registry-url : ' https://registry.npmjs.org/'
133- cache : ' pnpm' # Use pnpm cache
134-
135- - name : Install pnpm globally
136- run : npm install -g pnpm
154+ cache : ' pnpm'
137155
138- # Install only production dependencies before publishing (optional but good practice)
139- # - name: Install production dependencies
140- # run: npm ci --omit=dev
156+ # No need to install dependencies again if publish doesn't need them
157+ # If pnpm publish needs package.json, it's checked out
158+ - name : Install all dependencies for prepublishOnly script
159+ run : pnpm install --frozen-lockfile
141160
142- - name : Publish to npm with provenance
143- run : npm publish --access public --provenance # Added provenance
161+ - name : Publish to npm
162+ run : pnpm changeset publish
144163 env :
145- NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }} # Still needed for non-provenance or fallback
164+ NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
146165
147166 publish-docker :
148- needs : [validate, build] # Depends on validate and build
167+ name : Publish to Docker Hub
168+ needs : build-archive # Depends on build-archive completion
149169 runs-on : ubuntu-latest
150- if : startsWith(github.ref, 'refs/tags/v') # Condition: Only run for tags
151- permissions : # Added permissions for docker login
152- contents : read
153- packages : write
170+ if : startsWith(github.ref, 'refs/tags/v') # Only run for tags
154171 steps :
155- - name : Download build artifacts archive
156- uses : actions/download-artifact@v4.1.8 # Specific version
157- with :
158- name : ${{ needs.build.outputs.artifact_name }} # Use consistent artifact name
159- path : .
160-
161- - name : List downloaded files (docker)
162- run : ls -la
163-
164- - name : Extract build artifacts
165- run : tar -xzf build-artifacts.tar.gz # Use the correct archive filename
166-
167- - name : List extracted files (docker)
168- run : ls -la
172+ - name : Checkout repository
173+ uses : actions/checkout@v4.1.7
169174
170175 - name : Set up QEMU
171- uses : docker/setup-qemu-action@v3.2.0 # Specific version
176+ uses : docker/setup-qemu-action@v3.2.0
172177
173178 - name : Set up Docker Buildx
174- uses : docker/setup-buildx-action@v3.5.0 # Specific version
179+ uses : docker/setup-buildx-action@v3.5.0
175180
176181 - name : Log in to Docker Hub
177- uses : docker/login-action@v3.2.0 # Specific version
182+ uses : docker/login-action@v3.3.0
178183 with :
179184 username : ${{ secrets.DOCKERHUB_USERNAME }}
180185 password : ${{ secrets.DOCKERHUB_TOKEN }}
181186
182187 - name : Extract metadata (tags, labels) for Docker
183188 id : meta
184- uses : docker/metadata-action@v5.5.1 # Specific version
189+ uses : docker/metadata-action@v5.5.1
185190 with :
186- images : sylphlab/filesystem-mcp
191+ images : sylphlab/pdf-reader-mcp
192+ # Use version from the build-archive job output
187193 tags : |
188- type=semver,pattern={{version}},value=${{ needs.build.outputs.version }}
189- type=semver,pattern={{major}}.{{minor}},value=${{ needs.build.outputs.version }}
190- type=sha,prefix=,suffix=,event=tag
191- type=raw,value=latest,enable=${{ github.ref_type == 'tag' }} # Only tag latest on actual tag pushes
194+ type=semver,pattern={{version}},value=${{ needs.build-archive.outputs.version }}
195+ type=semver,pattern={{major}}.{{minor}},value=${{ needs.build-archive.outputs.version }}
196+ type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
192197
193198 - name : Build and push Docker image
194- uses : docker/build-push-action@v6.5.0 # Specific version
199+ uses : docker/build-push-action@v6.7.0
195200 with :
196201 context : .
197202 push : true
@@ -200,28 +205,26 @@ jobs:
200205 cache-from : type=gha
201206 cache-to : type=gha,mode=max
202207
203- create-release :
204- needs : [validate, build, publish-npm, publish-docker] # Depend on validate, build and both publish jobs
208+ release :
209+ name : Create GitHub Release
210+ needs : [publish-npm, publish-docker] # Depends on successful parallel publishes
205211 runs-on : ubuntu-latest
206- if : startsWith(github.ref, 'refs/tags/v') # Condition: Only run for tags
212+ if : startsWith(github.ref, 'refs/tags/v') # Only run for tags
207213 permissions :
208- contents : write # Keep write permission
214+ contents : write # Need permission to create releases and release notes
209215 steps :
210- - name : Download build artifacts archive
211- uses : actions/download-artifact@v4.1.8 # Specific version
216+ - name : Download build artifact
217+ uses : actions/download-artifact@v4.1.8
212218 with :
213- name : ${{ needs.build.outputs.artifact_name }} # Use consistent artifact name
214- path : .
215-
216- - name : Extract build artifacts
217- run : tar -xzf build-artifacts.tar.gz # Use the correct archive filename
219+ name : release-artifact
220+ # No path specified, downloads to current directory
218221
219222 - name : Create GitHub Release
220- uses : softprops/action-gh-release@v2.0.6 # Specific version
223+ uses : softprops/action-gh-release@v2.0.6
221224 with :
222225 tag_name : ${{ github.ref_name }}
223226 name : Release ${{ github.ref_name }}
224- body_path : CHANGELOG.md # Assumes CHANGELOG.md is in the artifact
225- # files: ${{ needs.build.outputs.archive_filename }} # Optionally attach the archive
227+ generate_release_notes : true # Auto-generate release notes from commits
228+ files : ${{ needs.build-archive .outputs.artifact_path }} # Attach the artifact archive from build-archive job
226229 env :
227230 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
0 commit comments