Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 21 additions & 16 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,27 @@ jobs:
- name: Install
run: npm ci --ignore-scripts
timeout-minutes: 10
# Note: when pushing to main we want to test only what changed in
# last commit. Otherwise we want to test all changes from origin/main.
# So we set the right values for base and head commits depending
# on the type of event (PR or push)
# ref: https://nx.dev/ci/features/affected#configure-affected-on-ci
- name: Set base and head commits
run: |
if [ "${{github.event_name}}" == "push" ]; then
echo "NX_BASE=origin/main~1" >> "$GITHUB_ENV"
echo "NX_HEAD=origin/main" >> "$GITHUB_ENV"
else
echo "NX_BASE=origin/main" >> "$GITHUB_ENV"
echo "NX_HEAD=HEAD" >> "$GITHUB_ENV"
fi
- name: Compile (Delta)
run: npm run compile:ci:affected

# Setting a global cache which key changes every day
- name: Set Cache Key
run: echo "CACHE_KEY=compile-cache-main-$(date +%Y-%m-%d)" >> "$GITHUB_ENV"
- name: Compile Cache Lookup
# if: ${{ github.event_name == 'pull_request' }}
uses: actions/cache/restore@v4
with:
key: ${{ env.CACHE_KEY }}
path: .nx
- name: Compile
run: npm run compile
- name: Update Cache (Push)
# if: ${{ github.event_name == 'push' }}
uses: actions/cache/save@v4
with:
key: ${{ env.CACHE_KEY }}
path: .nx

# Upload the compilation results as an artifact thta will be available
# only for this runa dn will be deleted in one day.
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ docs
#lerna
.changelog
.nx
.nx-server-cache

# OS generated files
.DS_Store
Expand Down
127 changes: 127 additions & 0 deletions scripts/nx-cache-server.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/env node
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Starts a custom server to provide caching to `nx` in CI
*
* See: https://nx.dev/docs/guides/tasks--caching/self-hosted-caching#build-your-own-caching-server
*
* Usage:
* NX_CACHE_SERVER_PORT=3000 NX_CACHE_SERVER_PATH=my-cache node scripts/nx-cache-server.mjs
*/

import { createReadStream, createWriteStream, existsSync, mkdirSync } from 'fs';
import { createServer } from 'http';

const port = process.env.NX_CACHE_SERVER_PORT;
const cachePath = process.env.NX_CACHE_SERVER_PATH;

const server = createServer((req, res) => {
const url = new URL(`http://localhost}${req.url}`);
const [version, resource, hash] = url.pathname.split('/').filter(s => s);
const verb = req.method.toUpperCase();

// Validation
// Auth token?

// Path is correct and contains hash
if (version !== 'v1' || resource !== 'cache' || typeof hash !== 'string') {
res.statusCode = 404;
res.end('Not found');
return;
}

if (verb === 'PUT') {
return setHash(req, res, hash);
} else if (verb === 'GET') {
return getHash(req, res, hash);
}

res.writeHead(400, {'Content-Type': 'text/plain'});
res.end('Invalid method.');
});

/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {string} hash
*/
function setHash(req, res, hash) {
const contentType = req.headers['content-type'];
const bodyLength = Number(req.headers['content-length']);
const invalidLength = isNaN(bodyLength);
const invalidType = contentType !== 'application/octet-stream';
if (invalidLength || invalidType) {
const errMsgs = [];
if (invalidLength) {
errMsgs.push('content-lenght must be a number')
}
if (invalidType) {
errMsgs.push('content-type must be application/octet-stream');
}
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end(`Invalid params: ${errMsgs.join(', ')}.`);
return;
}

// Ensure cache
if (!existsSync(cachePath)) {
mkdirSync(cachePath, { recursive: true });
}

// Do not override existing hashes?? -- yes for now
const entryPath = `${cachePath}/${hash}`
if (existsSync(entryPath)) {
res.statusCode = 409;
res.end('Cannot override an existing record.');
return;
}

// Pipe stream to a file
const writeStream = createWriteStream(entryPath);
req.pipe(writeStream);
req.on('end', () => {
req.statusCode = 200;
res.end();
});
}

/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @param {string} hash
*/
function getHash(req, res, hash) {
// no cache or no entry -> nothing to return
const entryPath = `${cachePath}/${hash}`
if (!existsSync(cachePath) || !existsSync(entryPath)) {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end('Not found.');
return;
}

// Pipe stream to a file
const readStream = createReadStream(entryPath);
readStream.pipe(res);
readStream.on('error', (err) => {
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end(`Unkonw error::: ${err}`);
})
}

console.log(`server listening to port ${port}`);
server.listen(port);
Loading