Getting Started With Workers
JFrog Workers provide a serverless, event-driven execution environment that allows you to extend the JFrog Platform with custom scripts. Instead of bending your business logic to fit a tool, Workers allow the platform to adapt to your unique needs.
This guide helps you identify how a Worker can solve your operational challenges, choose the right development interface, and build your first Worker. For more information, see Workers Overview.
Step 1: Identify the Problem
Before writing code, it is important to identify the specific pain point or gap in your workflow that a Worker can address. Teams often start by creating a simple Worker to solve a specific problem.
- Cross-Cluster Synchronization: Capture the upload origin region for asynchronous federation or cross-cluster syncing. Or synchronize entities like project across JFrog Platform installation on a schedule.
For more information, see Configure Scheduled Worker. - Automated Metadata Management: Eliminate manual tagging by using an After Create Worker to automatically apply a predefined set of properties to artifacts immediately upon upload. This ensures consistency in metadata and allows for high-speed querying.
For more information, see Configure Event-Driven Workers for Aftifactory. - Operational Governance and Redirection: Prevent standard users from uploading artifacts directly into shared or production repositories. A Before Upload Worker can intercept unauthorized uploads and redirect them to a quarantine repository for inspection.
For more information, see Configure Event-Driven Workers for Access. - Gradual Security Policy Adoption: Roll out new security policies without disrupting developer workflows. You can use Workers in a "dry run mode" to trigger notifications regarding curation and blocking events, alerting teams of potential issues before enforcing active blocking.
For more information, see Configure HTTP-Triggered Worker.
Step 2: Choose Your Development Interface
Once you know what you want to build, you can decide how to build and manage it. The JFrog Platform supports creating Workers through the UI or the JFrog CLI.
- JFrog CLI (Best Practice): To effectively leverage Workers at scale, treat your automation logic as production code. Using the JFrog CLI allows you to version-control your scripts, test them locally, and deploy them via CI/CD pipelines, allowing you also to deploy the same worker to multiple JPDs.
- JFrog Platform UI: The UI provides an excellent starting point for exploring capabilities. It features an intuitive TypeScript editor with autocompletion and a built-in testing pane, making it easy to create and validate a simple Worker quickly.
Step 3: Define the Worker
We will create an event-driven Worker that blocks uploads to JFrog Artifactory if the target path does not match a specific regex pattern. Choose your preferred method below to generate the skeleton code.
Using the JFrog CLI (Best Practice)
- Open your terminal and run the Worker initialization command:
jf worker init - Follow the interactive prompts:
- Select Event Driven Worker.
- Select the Before Upload action.
- Enter a name for your Worker (for example,
Path_checker).
This generates a local workspace with a configuration file (manifest.json), a skeleton TypeScript file (worker.ts), and a local testing file.
Using the JFrog Platform UI
- Log in to the JFrog Platform as an admin
- Navigate to Administration > Workers
- Click + New Worker > New Event Driven Worker
- Locate the Before Upload event, click Add, and select Start with Skeleton.
Step 4: Write the Action
The Worker service requires you to export an anonymous default function containing your custom logic. The script below intercepts an upload request and blocks it if the target path does not match a specific folder structure ending in .jar or .war.
This function accepts two essential parameters:
context: Your Worker's built-in toolbox. It provides utility functions and HTTP clients to securely interact with other JFrog Platform services.data: The JSON payload detailing the specific trigger event. For aBefore Uploadevent, this includes the target repository and file path. You will modify a simulated version of this payload when testing.
In the TypeScript editor, replace the skeleton code with the following script:
export default async (context: PlatformContext, data: BeforeUploadRequest): Promise<BeforeUploadResponse> => {
// This RegExp will match all repopaths that start with 'org/company/' and end with the extension .jar OR .war
const authorizedPathRegEx = /^org\/company\/(?:\w+.\/)+[\w\-\.]+\.(?:jar|war)$/;
let status: UploadStatus = UploadStatus.UPLOAD_UNSPECIFIED;
let message = "";
try {
if (authorizedPathRegEx.exec(data.metadata.repoPath.path)) {
status = UploadStatus.UPLOAD_PROCEED;
message = `RepoPath '${data.metadata.repoPath.path}' is acceptable for the repository '${data.metadata.repoPath.key}'`;
} else {
status = UploadStatus.UPLOAD_STOP;
message = `RepoPath '${data.metadata.repoPath.path}' does not match the regex ${authorizedPathRegEx} for the repository '${data.metadata.repoPath.key}'`;
}
} catch(error) {
status = UploadStatus.UPLOAD_WARN;
console.error(`could not check the path: ${error}`);
message = `An error occurred during the check. Proceed with warning.`;
}
return {
status,
message,
modifiedRepoPath: data.metadata.repoPath
}
}Step 5: Test and Enable the Worker
Always test your Worker before enabling it for live traffic.
Using the JFrog CLI (Best Practice)
- Open the generated testing file (for example,
worker.spec.ts) in your workspace. - Replace the content of the file with:
import { PlatformContext } from 'jfrog-workers'; import { BeforeUploadRequest, UploadStatus } from './types'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; import runWorker from './worker'; describe("Path_checker tests", () => { let context: DeepMocked<PlatformContext>; beforeAll(() => { context = createMock<PlatformContext>(); }) it.each([ { testCase: 'should accept uploading a jar file', path: 'org/company/folder/file.jar', expectedUploadStatus: UploadStatus.UPLOAD_PROCEED, }, { testCase: 'should accept uploading a war file', path: 'org/company/folder/file.war', expectedUploadStatus: UploadStatus.UPLOAD_PROCEED, }, { testCase: 'files in nested folder should be accepted', path: 'org/company/nested/folder/file.war', expectedUploadStatus: UploadStatus.UPLOAD_PROCEED, }, { testCase: 'should deny uploading a non-jar and non-war file', path: 'org/company/folder/file.pdf', expectedUploadStatus: UploadStatus.UPLOAD_STOP, }, { testCase: 'hould deny uploading a jar file that does not start with org/company', path: 'org/otherCompany/folder/file.jar', expectedUploadStatus: UploadStatus.UPLOAD_STOP, }, { testCase: 'hould deny uploading a war file that does not start with org/company', path: 'org/otherCompany/folder/file.war', expectedUploadStatus: UploadStatus.UPLOAD_STOP, }, { testCase: 'should deny uploading a file that is not in a folder', path: 'org/company/file.jar', expectedUploadStatus: UploadStatus.UPLOAD_STOP, } ])('$testCase', async ({path, expectedUploadStatus}) => { const request: DeepMocked<BeforeUploadRequest> = createMock<BeforeUploadRequest>({ metadata: { repoPath: { path, } } }); await expect(runWorker(context, request)).resolves.toEqual(expect.objectContaining({ status: expectedUploadStatus, modifiedRepoPath: { path }, })) }) it('should let pass the upload with warning in case of ', async () => { const request: DeepMocked<BeforeUploadRequest> = createMock<BeforeUploadRequest>({ metadata: {}, }); await expect(runWorker(context, request)).resolves.toEqual(expect.objectContaining({ status: UploadStatus.UPLOAD_WARN, modifiedRepoPath: undefined, })) }) }); - Open your terminal in the workspace directory and run your local tests to verify the logic:
npm installnpm test - Once the tests pass, open the
manifest.jsonfile. Under therepositoriesarray, add the key of the repository you want to monitor (for example,"maven"), and ensure theenabledproperty is set totrue. - Deploy and activate your Worker using the CLI:
jf worker deploy
Using the JFrog Platform UI
Before enabling the Worker for live traffic, test it to ensure it behaves as expected.
- In the Testing pane, modify the
pathproperty in the data structure to simulate an allowed upload request:"path": "org/company/package1/subPackage/webapp.war". - Click Run. The Execution Results pane will display a success status (
1), indicating the upload would proceed. - Do the same with
"path": "org/company/package1/subPackage/webapp.pdf". The Execution Results pane will display a status (2), indicating the upload would be rejected. - Enter a name for your Worker in the Name field. For example, enter
Path_checker. - Click the Settings (⚙️) icon
- Next to Repositories, click the + icon, select the repository you want this Worker to monitor, and click OK.
- Select the Enable Worker checkbox to activate it, then click Save.
Your Worker is now actively monitoring the selected repository and will block any uploads that do not comply with your organization's pathing rules.
Updated 4 days ago
