Skip to content

Commit d1d571e

Browse files
Merge pull request #2 from CodeSignal/deployment-setup
Add Vite-integration and sample GH action workflow
2 parents e320e0e + 465a316 commit d1d571e

File tree

9 files changed

+1662
-48
lines changed

9 files changed

+1662
-48
lines changed

.DS_Store

-8 KB
Binary file not shown.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
build-and-release:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v4
17+
18+
- name: Setup Node.js
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: '22.13.1'
22+
cache: 'npm'
23+
24+
- name: Install all dependencies
25+
run: npm ci
26+
27+
- name: Build project
28+
run: npm run build
29+
30+
- name: Install production dependencies only
31+
run: |
32+
npm ci --production
33+
34+
- name: Create release tarball
35+
run: |
36+
tar -czf release.tar.gz dist/ package.json server.js node_modules/
37+
38+
- name: Upload build artifact (for workflow logs)
39+
uses: actions/upload-artifact@v4
40+
with:
41+
name: dist
42+
path: dist
43+
44+
- name: Create GitHub Release and upload asset
45+
uses: ncipollo/release-action@v1
46+
with:
47+
token: ${{ secrets.GITHUB_TOKEN }}
48+
tag: v${{ github.run_number }}
49+
name: Release ${{ github.run_number }}
50+
body: |
51+
Latest build from main branch.
52+
artifacts: release.tar.gz
53+
allowUpdates: false
54+
draft: false
55+
prerelease: false
56+
makeLatest: true

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
2-
2+
dist/
3+
.DS_Store

README.md

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ A template for creating consistent help content:
3636

3737
### Setting Up a New Application
3838

39-
1. **Fork the repository**
39+
1. **Clone the repository**
4040
2. **Customize the HTML template** by replacing placeholders:
4141
- `<!-- APP_TITLE -->` - Your application title
4242
- `<!-- APP_NAME -->` - Your application name (appears in header)
@@ -108,10 +108,41 @@ This template includes a local development server (`server.js`) that provides:
108108
### Starting the Server
109109

110110
```bash
111-
node server.js
111+
# Local development
112+
npm run start:dev # Vite + API for local development
113+
# Production
114+
npm run build # Create production build in dist/
115+
npm run start:prod # Serve built assets from dist/
112116
```
113117

114-
The server will start on `http://localhost:3000` by default.
118+
119+
### Environment Variables
120+
121+
The server supports the following environment variables:
122+
123+
- **`PORT`** - Server port number
124+
- Development: Can be set to any port (e.g., `PORT=3001`), defaulting to `3000`
125+
- Production: Ignored (always `3000` when `IS_PRODUCTION=true`)
126+
127+
- **`IS_PRODUCTION`** - Enables production mode
128+
- Set to `'true'` to enable production mode
129+
- When enabled:
130+
- Server serves static files from `dist/` directory
131+
- Port is forced to `3000`
132+
- Requires `dist/` directory to exist (throws error if missing)
133+
134+
135+
### Vite Build System
136+
137+
This project uses [Vite](https://vitejs.dev/) as the build tool for fast development and optimized production builds.
138+
139+
#### Build Process
140+
141+
Running `npm run build` executes `vite build`, which:
142+
- Reads source files from the `client/` directory (configured in `vite.config.js`)
143+
- Processes and bundles JavaScript, CSS, and other assets
144+
- Outputs optimized production files to the `dist/` directory
145+
- Generates hashed filenames for cache busting
115146

116147
### WebSocket Messaging API
117148

@@ -138,3 +169,31 @@ curl -X POST http://localhost:3000/message \
138169
-H "Content-Type: application/json" \
139170
-d '{"message": "Hello from the server!"}'
140171
```
172+
173+
## CI/CD and Automated Releases
174+
175+
This template includes a GitHub Actions workflow (`.github/workflows/build-release.yml`) that automatically builds and releases your application when you push to the `main` branch.
176+
177+
### How It Works
178+
179+
When you push to `main`, the workflow will:
180+
181+
1. **Build the project** - Runs `npm run build` to create production assets in `dist/`
182+
2. **Create a release tarball** - Packages `dist/`, `package.json`, `server.js`, and production `node_modules/` into `release.tar.gz`
183+
3. **Create a GitHub Release** - Automatically creates a new release tagged as `v{run_number}` with the tarball attached
184+
185+
### Release Contents
186+
187+
The release tarball (`release.tar.gz`) contains everything needed to deploy the application:
188+
- `dist/` - Built production assets
189+
- `package.json` - Project dependencies and scripts
190+
- `server.js` - Production server
191+
- `node_modules/` - Production dependencies only
192+
193+
### Using Releases
194+
195+
To deploy a release:
196+
197+
1. Download `release.tar.gz` from the latest GitHub Release (e.g. with `wget`)
198+
2. Extract (and remove) the tarball: `tar -xzf release.tar.gz && rm release.tar.gz`
199+
3. Start the production server: `npm run start:prod`

client/app.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111
function initializeWebSocket() {
1212
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
1313
const host = window.location.host;
14-
const wsUrl = `${protocol}//${host}`;
15-
14+
const wsUrl = `${protocol}//${host}/ws`;
15+
1616
try {
1717
websocket = new WebSocket(wsUrl);
18-
18+
1919
websocket.onopen = function(event) {
2020
console.log('WebSocket connected');
2121
setStatus('Ready (WebSocket connected)');
2222
};
23-
23+
2424
websocket.onmessage = function(event) {
2525
try {
2626
const data = JSON.parse(event.data);
@@ -31,23 +31,23 @@
3131
console.error('Error parsing WebSocket message:', error);
3232
}
3333
};
34-
34+
3535
websocket.onclose = function(event) {
3636
console.log('WebSocket disconnected');
3737
setStatus('Ready (WebSocket disconnected)');
38-
38+
3939
// Attempt to reconnect after 3 seconds
4040
setTimeout(() => {
4141
console.log('Attempting to reconnect WebSocket...');
4242
initializeWebSocket();
4343
}, 3000);
4444
};
45-
45+
4646
websocket.onerror = function(error) {
4747
console.error('WebSocket error:', error);
4848
setStatus('Ready (WebSocket error)');
4949
};
50-
50+
5151
} catch (error) {
5252
console.error('Failed to create WebSocket connection:', error);
5353
setStatus('Ready (WebSocket unavailable)');

0 commit comments

Comments
 (0)