CI/CD Pipeline Integration
This guide shows how to integrate ByteHide Shield into various CI/CD pipelines for automated JavaScript protection during your build process.
ByteHide Shield can be seamlessly integrated into your CI/CD pipelines to automatically protect your JavaScript code during the build and deployment process. This ensures your code is protected consistently across all environments without manual intervention.
Integration Overview
How CI/CD Integration Works
The integration process follows a standard pattern across all CI/CD platforms:
- Build Phase: Your application is built normally using your existing build tools (npm, webpack, etc.)
- Shield Installation: The ByteHide Shield CLI is installed in the CI/CD environment
- Protection Phase: Shield analyzes and protects the generated JavaScript files
- Deployment: The protected files are deployed to your target environment
Integration Approaches
There are three main approaches to integrate ByteHide Shield into your CI/CD pipeline:
Option A: Configuration File (Recommended)
- Store your Shield configuration in a
shield.config.json
file in your repository - Reference your project token via environment variables within the config
- Provides version control for your protection settings
- Allows different configurations per environment
Option B: Direct Token Usage
- Pass the project token directly via command line flags
- Simpler setup but less flexible for complex configurations
- Good for quick implementations or simple protection needs
Option C: Dynamic Configuration
- Create the configuration file during the CI/CD process
- Combines flexibility of config files with dynamic token injection
- Useful when different branches need different protection levels
Prerequisites
Before implementing CI/CD integration, ensure you have:
- A ByteHide Shield project token (see Get Project Token)
- Your CI/CD platform configured with secret management
- Understanding of your application's build output structure
- Node.js 14+ available in your CI/CD environment
Security Considerations
Token Security
Never commit your project token to source control. Always use your CI/CD platform's secret management system to store and inject the token securely.
When integrating Shield into CI/CD pipelines:
- Store tokens as encrypted secrets in your CI/CD platform
- Use environment variables to pass tokens to the Shield CLI
- Limit token access to authorized team members only
- Consider using different tokens for different environments
- Regularly rotate your project tokens for enhanced security
Framework-Specific Considerations
Different JavaScript frameworks generate files in different locations and patterns:
- Next.js: Generates chunks in
.next/static/chunks/
that should be protected - Angular: Creates main bundles in
dist/
folder, typicallymain*.js
files - React (CRA): Outputs static files to
build/static/js/
directory - Vue.js: Places compiled files in
dist/js/
folder - Webpack: Can output to any configured directory, commonly
dist/
- Vite: Generates assets in
dist/assets/
directory
Understanding your framework's output structure is crucial for targeting the correct files for protection.
Azure DevOps Integration
Next.js Applications
For Next.js applications, you'll want to protect the generated chunks in the .next/static/chunks/
directory:
# azure-pipelines-nextjs.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
# Used only if you choose the --token option (see commented step)
SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
steps:
- checkout: self
clean: true
- task: UseNode@1
inputs:
version: '18.x'
- script: |
npm ci
npm i -g @bytehide/shield-cli
displayName: 'Install deps & Shield CLI'
- script: |
npm run build
displayName: 'Build Next.js'
# --- Option A (ACTIVE): Use an existing config file tracked in the repo ---
# Note: Place your config at: pipeline/shield.config.json (or adjust the path)
- script: |
shield protect ".next/static/chunks/**/*.js" --config pipeline/shield.config.json
displayName: 'Shield protect (Next.js chunks via config)'
# --- Option B (COMMENTED): Use --token directly (no config file) ---
# - script: |
# shield protect ".next/static/chunks/**/*.js" --token "$(SHIELD_PROJECT_TOKEN)"
# displayName: 'Shield protect (Next.js chunks via token)'
# --- Option C (COMMENTED): Create the config file here and then use it ---
# - script: |
# mkdir -p pipeline
# cat > pipeline/shield.config.json <<'JSON'
# {
# "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
# "devtoolsBlocking": false
# }
# JSON
# shield protect ".next/static/chunks/**/*.js" --config pipeline/shield.config.json
# displayName: 'Create config & Shield protect (Next.js)'
Angular Applications
For Angular applications, you'll typically want to protect the main bundle files:
# azure-pipelines-angular.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
# Used only if you choose the --token option (see commented step)
SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
steps:
- checkout: self
clean: true
- task: UseNode@1
inputs:
version: '18.x'
- script: |
cd src/Vendor_Portal/app
npm ci
npm i -g @bytehide/shield-cli
displayName: 'Install deps & Shield CLI'
- script: |
cd src/Vendor_Portal/app
npm run build
displayName: 'Build Angular'
# --- Option A (ACTIVE): Use an existing config file tracked in the repo ---
# Note: The config lives at repository root "pipeline/shield.config.json".
# We call it from app folder, so the relative path is ../../../pipeline/shield.config.json
- script: |
cd src/Vendor_Portal/app
shield protect "dist/vendor_portal/main*.js" --config ../../../pipeline/shield.config.json
displayName: 'Shield protect (Angular main via config)'
# --- Option B (COMMENTED): Use --token directly (no config file) ---
# - script: |
# cd src/Vendor_Portal/app
# shield protect "dist/vendor_portal/main*.js" --token "$(SHIELD_PROJECT_TOKEN)"
# displayName: 'Shield protect (Angular main via token)'
# --- Option C (COMMENTED): Create the config file here and then use it ---
# - script: |
# mkdir -p pipeline
# cat > pipeline/shield.config.json <<'JSON'
# {
# "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
# "devtoolsBlocking": false
# }
# JSON
# cd src/Vendor_Portal/app
# shield protect "dist/vendor_portal/main*.js" --config ../../../pipeline/shield.config.json
# displayName: 'Create config & Shield protect (Angular)'
React Applications
For React applications built with Create React App or similar:
# azure-pipelines-react.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
steps:
- checkout: self
clean: true
- task: UseNode@1
inputs:
version: '18.x'
- script: |
npm ci
npm i -g @bytehide/shield-cli
displayName: 'Install deps & Shield CLI'
- script: |
npm run build
displayName: 'Build React'
- script: |
shield protect "build/static/js/**/*.js" --config pipeline/shield.config.json
displayName: 'Shield protect (React static JS)'
Vue.js Applications
For Vue.js applications:
# azure-pipelines-vue.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
steps:
- checkout: self
clean: true
- task: UseNode@1
inputs:
version: '18.x'
- script: |
npm ci
npm i -g @bytehide/shield-cli
displayName: 'Install deps & Shield CLI'
- script: |
npm run build
displayName: 'Build Vue.js'
- script: |
shield protect "dist/js/**/*.js" --config pipeline/shield.config.json
displayName: 'Shield protect (Vue.js dist)'
Webpack Applications
For custom Webpack applications:
# azure-pipelines-webpack.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
steps:
- checkout: self
clean: true
- task: UseNode@1
inputs:
version: '18.x'
- script: |
npm ci
npm i -g @bytehide/shield-cli
displayName: 'Install deps & Shield CLI'
- script: |
npm run build
displayName: 'Build with Webpack'
- script: |
shield protect "dist/**/*.js" --config pipeline/shield.config.json
displayName: 'Shield protect (Webpack dist)'
GitHub Actions Integration
GitHub Actions provides a powerful and flexible platform for implementing ByteHide Shield protection in your workflows.
Setup Process for GitHub Actions
- Create Workflow File: Add a
.github/workflows/
YAML file to your repository - Configure Secrets: Add your
SHIELD_PROJECT_TOKEN
to your repository secrets - Define Build Steps: Set up Node.js, install dependencies, and build your application
- Install Shield CLI: Add the ByteHide Shield CLI as a global package
- Protect Files: Run Shield protection on your built JavaScript files
- Handle Artifacts: Upload or deploy the protected files
GitHub Secrets Configuration
Before implementing the workflows, configure your project token:
- Go to your repository Settings → Secrets and variables → Actions
- Click New repository secret
- Name:
SHIELD_PROJECT_TOKEN
- Value: Your ByteHide Shield project token
- Click Add secret
Workflow Triggers
You can configure different triggers for your protection workflows:
- Push to main branch: Protect code when merging to production
- Pull requests: Validate protection works before merging
- Manual dispatch: Allow manual triggering for testing
- Scheduled runs: Regular protection for dependency updates
Next.js with GitHub Actions
# .github/workflows/nextjs-protection.yml
name: Build and Protect Next.js
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-protect:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: |
npm ci
npm install -g @bytehide/shield-cli
- name: Build Next.js
run: npm run build
- name: Protect with Shield
env:
SHIELD_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}
run: |
shield protect ".next/static/chunks/**/*.js" --config pipeline/shield.config.json
- name: Upload protected build
uses: actions/upload-artifact@v4
with:
name: protected-nextjs-app
path: .next/
Angular with GitHub Actions
# .github/workflows/angular-protection.yml
name: Build and Protect Angular
on:
push:
branches: [ main ]
jobs:
build-and-protect:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: |
npm ci
npm install -g @bytehide/shield-cli
- name: Build Angular
run: npm run build
- name: Protect with Shield
env:
SHIELD_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}
run: |
shield protect "dist/*/main*.js" --config pipeline/shield.config.json
- name: Upload protected build
uses: actions/upload-artifact@v4
with:
name: protected-angular-app
path: dist/
GitLab CI Integration
GitLab CI/CD provides comprehensive DevOps capabilities with integrated security features that work well with ByteHide Shield.
GitLab CI/CD Setup Process
- Create Pipeline File: Add a
.gitlab-ci.yml
file to your repository root - Configure CI/CD Variables: Set up your
SHIELD_PROJECT_TOKEN
in GitLab's CI/CD settings - Define Stages: Typically use separate stages for build, protect, and deploy
- Configure Artifacts: Use GitLab's artifact system to pass files between stages
- Set Dependencies: Ensure protection stage depends on build completion
GitLab Variables Configuration
Configure your project token in GitLab:
- Go to your project Settings → CI/CD → Variables
- Click Add variable
- Key:
SHIELD_PROJECT_TOKEN
- Value: Your ByteHide Shield project token
- Check Protect variable and Mask variable for security
- Click Add variable
Pipeline Architecture
GitLab CI/CD pipelines for Shield protection typically use this structure:
- Build Stage: Compile your application and create artifacts
- Protect Stage: Install Shield CLI and protect the built files
- Test Stage (optional): Run tests on protected code
- Deploy Stage: Deploy the protected application
Docker Image Considerations
When using Docker images in GitLab CI:
- Use Node.js images (node:18 or later) that include npm
- Consider using custom images with Shield CLI pre-installed for faster builds
- Ensure proper permissions for file modifications during protection
Next.js with GitLab CI
# .gitlab-ci.yml
stages:
- build
- protect
- deploy
variables:
NODE_VERSION: "18"
before_script:
- apt-get update -qq && apt-get install -y nodejs npm
- npm ci
build:
stage: build
script:
- npm run build
artifacts:
paths:
- .next/
expire_in: 1 hour
protect:
stage: protect
script:
- npm install -g @bytehide/shield-cli
- shield protect ".next/static/chunks/**/*.js" --config pipeline/shield.config.json
artifacts:
paths:
- .next/
dependencies:
- build
Angular with GitLab CI
# .gitlab-ci.yml for Angular
stages:
- build
- protect
- deploy
variables:
NODE_VERSION: "18"
build:
stage: build
image: node:18
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
protect:
stage: protect
image: node:18
script:
- npm install -g @bytehide/shield-cli
- shield protect "dist/*/main*.js" --config pipeline/shield.config.json
artifacts:
paths:
- dist/
dependencies:
- build
Jenkins Integration
Jenkins provides extensive flexibility for implementing ByteHide Shield protection through its pipeline-as-code approach and plugin ecosystem.
Jenkins Setup Process
- Install Required Plugins: Ensure Node.js and Pipeline plugins are installed
- Configure Node.js: Set up Node.js installations in Jenkins Global Tool Configuration
- Create Pipeline: Set up a new Pipeline job or use a Jenkinsfile in your repository
- Configure Credentials: Add your Shield project token to Jenkins credentials store
- Define Stages: Structure your pipeline with build, protect, and deploy stages
Jenkins Credentials Configuration
Configure your project token in Jenkins:
- Go to Manage Jenkins → Manage Credentials
- Select the appropriate domain (usually Global)
- Click Add Credentials
- Kind: Secret text
- Secret: Your ByteHide Shield project token
- ID:
shield-project-token
(or your preferred identifier) - Description:
ByteHide Shield Project Token
- Click OK
Pipeline Architecture Options
Jenkins offers multiple ways to structure your protection pipeline:
Declarative Pipeline (Recommended)
- Uses a more structured syntax
- Better for teams new to Jenkins
- Easier to read and maintain
- Built-in directive support
Scripted Pipeline
- More flexible and powerful
- Uses Groovy syntax
- Better for complex logic
- Suitable for advanced users
Node.js Tool Configuration
Ensure Node.js is properly configured:
- Go to Manage Jenkins → Global Tool Configuration
- Find NodeJS section
- Add a NodeJS installation (version 18 or later)
- Reference this installation in your pipeline
Jenkinsfile for Next.js
pipeline {
agent any
environment {
SHIELD_PROJECT_TOKEN = credentials('shield-project-token')
}
stages {
stage('Install Dependencies') {
steps {
sh 'npm ci'
sh 'npm install -g @bytehide/shield-cli'
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('Protect with Shield') {
steps {
sh 'shield protect ".next/static/chunks/**/*.js" --config pipeline/shield.config.json'
}
}
stage('Archive Artifacts') {
steps {
archiveArtifacts artifacts: '.next/**/*', fingerprint: true
}
}
}
}
Framework-Specific Protection Patterns
Different frameworks generate JavaScript files in different locations. Use these patterns to target the correct files for protection.
Next.js Protection Patterns
# Protect all chunk files (recommended)
shield protect ".next/static/chunks/**/*.js"
# Protect specific chunks only
shield protect ".next/static/chunks/pages/**/*.js"
shield protect ".next/static/chunks/app/**/*.js"
Angular Protection Patterns
# Protect main bundle (most common)
shield protect "dist/*/main*.js"
# Protect all bundles
shield protect "dist/*/*.js"
# Protect specific bundles
shield protect "dist/*/main*.js" "dist/*/polyfills*.js"
React (CRA) Protection Patterns
# Protect all static JS files
shield protect "build/static/js/**/*.js"
# Protect only main chunks
shield protect "build/static/js/main*.js"
Vue.js Protection Patterns
# Protect all generated JS
shield protect "dist/js/**/*.js"
# Protect specific chunks
shield protect "dist/js/app*.js" "dist/js/chunk-vendors*.js"
Webpack Protection Patterns
# Protect all output files
shield protect "dist/**/*.js"
# Protect specific bundles
shield protect "dist/bundle*.js" "dist/vendor*.js"
Vite Protection Patterns
# Protect all assets
shield protect "dist/assets/**/*.js"
# Protect specific files
shield protect "dist/assets/index*.js"
Configuration Management
Proper configuration management is crucial for successful CI/CD integration. ByteHide Shield offers flexible configuration options to accommodate different deployment strategies and security requirements.
Security Best Practice
Never commit your project token directly to your repository. Always use environment variables or your CI/CD platform's secret management system.
Configuration Strategy Overview
When integrating Shield into CI/CD pipelines, you need to balance security, maintainability, and flexibility. Consider these factors:
- Token Security: How will you securely pass the project token?
- Environment Differences: Do you need different protection levels for staging vs. production?
- Team Access: Who needs access to modify protection settings?
- Version Control: Should protection settings be versioned with your code?
Configuration Options Comparison
Approach | Security | Flexibility | Maintenance | Best For |
---|---|---|---|---|
Config File | High | High | Easy | Teams with consistent settings |
Direct Token | Medium | Low | Easy | Simple, single-environment setups |
Dynamic Config | High | Very High | Medium | Multi-environment, complex deployments |
Option 1: Configuration File (Recommended)
Create a pipeline/shield.config.json
file in your repository:
{
"ProjectToken": "${SHIELD_PROJECT_TOKEN}",
"controlFlowFlattening": true,
"debugProtection": false,
"devtoolsBlocking": true,
"deadCodeInjection": false,
"selfDefending": true,
"stringArray": true,
"stringArrayEncoding": ["base64"],
"stringArrayThreshold": 0.8,
"transformObjectKeys": true,
"unicodeEscapeSequence": false
}
Option 2: Environment Token
Set the token as an environment variable and use it directly:
shield protect "dist/**/*.js" --token "$SHIELD_PROJECT_TOKEN"
Option 3: Dynamic Configuration
Create the configuration file during the CI/CD process:
# Create config dynamically
cat > pipeline/shield.config.json <<JSON
{
"ProjectToken": "$SHIELD_PROJECT_TOKEN",
"devtoolsBlocking": false,
"controlFlowFlattening": true
}
JSON
# Use the created config
shield protect "dist/**/*.js" --config pipeline/shield.config.json
Environment Setup
Setting Up Secrets
In your CI/CD platform, add the following environment variables:
Platform | Variable Name | Description |
---|---|---|
Azure DevOps | SHIELD_PROJECT_TOKEN | Library variable or variable group |
GitHub Actions | SHIELD_PROJECT_TOKEN | Repository secret |
GitLab CI | SHIELD_PROJECT_TOKEN | CI/CD variable (protected) |
Jenkins | SHIELD_PROJECT_TOKEN | Credentials (secret text) |
Node.js Version Requirements
ByteHide Shield CLI requires Node.js 14 or newer. For older Node.js versions (12-13), use @bytehide/shield-cli-legacy
.
Ensure your CI/CD environment uses a compatible Node.js version:
# Azure DevOps
- task: UseNode@1
inputs:
version: '18.x'
# GitHub Actions
- uses: actions/setup-node@v4
with:
node-version: '18'
# GitLab CI
image: node:18
Advanced Integration Patterns
Multi-Environment Protection
Protect different files based on the environment:
# Development - minimal protection
if [ "$NODE_ENV" = "development" ]; then
shield protect "dist/**/*.js" --config pipeline/shield.dev.config.json
fi
# Production - full protection
if [ "$NODE_ENV" = "production" ]; then
shield protect "dist/**/*.js" --config pipeline/shield.prod.config.json
fi
Conditional Protection
Only protect on specific branches or conditions:
# GitHub Actions - only protect on main branch
- name: Protect with Shield
if: github.ref == 'refs/heads/main'
run: shield protect "dist/**/*.js" --config pipeline/shield.config.json
# Azure DevOps - condition example
- script: |
shield protect "dist/**/*.js" --config pipeline/shield.config.json
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
displayName: 'Shield protect (main branch only)'
Parallel Jobs
For large applications, you can protect different file patterns in parallel:
# GitHub Actions - parallel protection
jobs:
protect-main:
runs-on: ubuntu-latest
steps:
# ... build steps ...
- name: Protect main files
run: shield protect "dist/main*.js" --config pipeline/shield.config.json
protect-chunks:
runs-on: ubuntu-latest
steps:
# ... build steps ...
- name: Protect chunk files
run: shield protect "dist/chunks/**/*.js" --config pipeline/shield.config.json
Troubleshooting
Common Issues
Build Artifact Not Found
If the protection step can't find the built files:
# Add debugging to see what files exist
ls -la dist/
ls -la .next/static/chunks/
# Then adjust your protection pattern accordingly
Permission Issues
Ensure the CI/CD agent has proper permissions:
# Make sure files are writable
chmod -R 755 dist/
# Verify the protection command
shield protect "dist/**/*.js" --dry-run
Token Authentication Failed
Verify your token is correctly set:
# Debug token (be careful in logs)
echo "Token length: ${#SHIELD_PROJECT_TOKEN}"
# Test with a simple command
shield --version
Performance Optimization
For large applications, consider:
- Protecting only critical files instead of all JavaScript files
- Using parallel jobs to protect different file patterns
- Caching node_modules between builds
- Using specific glob patterns instead of broad wildcards
Next Steps
- Learn about Configuration Files for customizing protection settings
- Explore Protection Options to understand available security features
- Check out CLI Installation for more CLI usage examples
- Review Source Maps for debugging protected code