Setup GitHub Repository Onboarding with Harness IDP
This tutorial shows you how to create a self-service GitHub repository onboarding workflow using Harness IDP. The workflow allows developers to create and configure new GitHub repositories automatically through a simple UI form interface. This eliminates manual repository setup and ensures consistency across all projects.
Goals of the Workflow
By the end of this tutorial, you'll have a working workflow that delivers:
- Automated Repository Creation: New GitHub repositories are created instantly with proper configuration
- Automated Creation of Branch and Files: New branches and files are created and pushed to the repository automatically without any manual intervention.
- Security Best Practices: Branch protection rules are automatically applied to enforce code reviews
- CI/CD Integration: Webhooks are configured to trigger automated pipelines on specific changes
- Self-Service Experience: Developers can create repositories without platform team intervention
Workflow Components
The GitHub repository onboarding workflow consists of two main components that work together:
1. Harness Pipeline
This orchestration pipeline contains all the automation logic and executes the actual repository creation steps. This Harness IDP pipeline serves as the orchestration backend for our GitHub repository onboarding workflow. Think of it as the engine that powers the automation - when a developer fills out the workflow form (the UI part), this pipeline executes all the technical steps needed to create and configure a GitHub repository.
2. Harness IDP Workflow
The Workflow provides a user-friendly interface where developers input the following details and can create a repository without any intervention and runs the above orchestration pipeline in backend to execute the final actions of the Workflow. The Workflow includes validation to ensure proper input format and triggers the above pipeline execution to ensure all the steps are executed successfully.
The following input details are required for the Workflow:
- Repository name and description
- GitHub organization
- Feature branch name
Prerequisites
-
Harness IDP enabled for your Account: Ensure you have access to Harness with the Internal Developer Portal (IDP) module enabled.
-
GitHub Connector: A GitHub connector must be set up and configured to authenticate with your GitHub organization. This connector is used by the
CreateRepo
andDirectPush
steps to interact with GitHub APIs securely. Go to GitHub Connector to learn more. -
GitHub PAT Token: A Personal Access Token (PAT) with appropriate permissions (
repo
,admin:repo_hook
,admin:org_hook
) is needed for GitHub API operations. The pipeline uses this token in theRun
steps to execute GitHub API calls for branch creation, branch protection setup, and webhook configuration. Go to GitHub PAT to learn more. -
Workflow YAML & Harness IDP Pipeline configuration: Basic familiarity with Workflow YAML syntax and Harness pipeline configuration is recommended. Understanding YAML structure helps in configuring pipeline variables and step parameters correctly. Go to Workflow YAML and Harness IDP Pipeline to learn more.
Create the GitHub Repository Onboarding Pipeline
This Harness IDP pipeline serves as the orchestration backend for our GitHub repository onboarding workflow. In this section, we'll go through all the steps required to develop this orchestration pipeline for this Workflow.
Pipeline Design
Steps involved in this Pipeline:
The following steps will be executed in this pipeline:
- Step 1: Create a new GitHub repository with proper configuration
- Step 2: Set up a feature branch for development
- Step 3: Create a directory
- Step 4: Create standard project files
- Step 5: Push the files to the feature branch
- Step 6: Configure branch protection rules for security
- Step 7: Set up webhooks for CI/CD integration
Pipeline Execution:
The pipeline is triggered automatically when a developer submits the IDP workflow form. The workflow acts as the user interface, collecting input parameters, while this pipeline handles the backend automation. For more detailed information about Harness IDP pipelines, refer to the Harness IDP Pipeline Documentation.
Get Started
Let's walk through setting up this pipeline step by step:
Step 1: Create a New Pipeline
- Navigate to your Harness project.
- Go to Pipelines in the left sidebar from Harness IDP.
- Click + Create a Pipeline
- Choose Inline pipeline creation
- Enter the following details:
- Name:
GitHub Repository Onboarding
- Description:
Automated GitHub repository creation and configuration pipeline
- Name:
Step 2: Add a Developer Portal Stage
Once you're inside the pipeline editor:
- Click + Add Stage.
- Select Developer Portal as the stage type.
This opens a stage configuration screen with four tabs: Overview, Infrastructure, Execution, and Advanced.
Here’s what you’ll do in each tab:
1. Overview
Give your stage a name (for example, GitHub Repo Onboarding
).
You can also add a brief description to explain what this stage handles — such as generating code and registering the service.
2. Infrastructure
Next, choose where the pipeline should run.
- If you want a simple setup, go with Harness Cloud Infrastructure.
- If you prefer running the scripts in your own environment (like Kubernetes or a Docker runner), choose a custom delegate.
3. Execution
This is where you'll define the main orchestration logic for the pipeline. You can add execution steps directly in this section.
You don’t need to configure this yet; we’ll walk through each of these steps in the next section.
Advanced (optional)
You can leave this tab as-is unless you need to configure timeouts or failure handling. This is optional.
- Interactive Guide
- YAML
pipeline:
name: github-repo-onb
identifier: githubrepoonb
projectIdentifier: idpprojectsc
orgIdentifier: neworg
tags: {}
stages:
- stage:
name: github-repo
identifier: githubrepo
description: ""
type: IDP
spec:
platform:
os: Linux
arch: Amd64
runtime:
type: Cloud
spec: {}
tags: {}
Step 3: Configure Pipeline Variables
Pipeline variables are essential components that make your pipeline reusable and dynamic. These variables serve as inputs to the onboarding pipeline; some will come from the developer via the workflow form, while others are fixed or derived values used internally by the pipeline.
Pipeline Variables:
These variables are used in the GitHub Repository Onboarding pipeline for our Workflow:
Variable Name | Type | Source | Description | Example Value |
---|---|---|---|---|
repo_name | String | User Input | Name of the repository to create | my-awesome-project |
org_name | String | User Input | GitHub organization name | my-organization |
repo_branch_name | String | User Input | Feature branch name for initial development | feature/initial-setup |
token | Secret | Fixed | GitHub personal access token for API operations | account.github-token |
webhook_url | String | Fixed | Webhook URL for CI/CD integration | https://app.harness.io/gateway/... |
repo_desc (Optional) | String | User Input | Repository description | A new project created via IDP |
Pipeline Variables Input Types:
In Harness pipelines, every variable is assigned one of the following types, based on how its value is provided or resolved during execution:
- Fixed - These values are hardcoded in the pipeline definition and remain constant for every run.
- Runtime Input - These values are left as
<+input>
and are filled in by the developer through the IDP Workflow form when the onboarding process is triggered. - Expression - These values are computed dynamically during pipeline execution using expressions. They may reference other variables, pipeline context, or system values.
These variables will be referenced in your pipeline steps using the <+pipeline.variables.variable_name>
syntax, and they ensure flexibility while keeping your pipeline reusable across multiple onboarding requests. Go to Variables & Expressions to learn more.
Runtime Inputs in our Workflow:
In our GitHub Repository Onboarding workflow, most of the pipeline variables are configured as runtime inputs (<+input>
) because they originate from user inputs collected through the IDP workflow form.
When a developer executes the workflow, they provide specific details like repository name, organization name, branch name, and webhook URL through the user interface. These user-provided values are then passed to the pipeline as runtime inputs, making each pipeline execution unique and tailored to the developer's requirements. Only the GitHub token remains as a fixed secret value since it's pre-configured in Harness for security purposes.
Configuring Pipeline Variables:
Follow these steps to add the required pipeline variables:
- Navigate to the Variables tab in your pipeline editor.
- For each variable, set the Type and Description
- In the Value field, enter
<+input>
for user-provided values - For secrets, reference the secret name (e.g.,
account.github-token
) - Mark variables as Required if they're essential for pipeline execution
Note that token
and webhook_url
are fixed values since they are pre-configured. Provide the value of webhook_url
in the variable input as a fixed value. For token
configuration, select the variable type as secret and configure the secret from your secret manager. Check out the interactive guide below for detailed steps.
- Interactive Guide
- YAML
variables:
- name: repo_name
type: String
description: "Name of the repository to create"
required: true
value: <+input>
- name: org_name
type: String
description: "GitHub organization name"
required: true
value: <+input>
- name: repo_desc
type: String
description: "Repository description"
required: true
value: <+input>
- name: repo_branch_name
type: String
description: "Feature branch name"
required: true
value: <+input>
- name: token
type: Secret
description: "GitHub personal access token"
required: true
value: account.github-token
- name: webhook_url
type: String
description: "Webhook URL for CI/CD integration"
required: true
value: <+input>
Step 1: Create Repository
Purpose: This pipeline step creates a new GitHub repository in the specified organization with the provided repository name and description.
This step will do the following:
- Create a new GitHub repository in the specified organization
- Set up the repository with the provided name and description
Prerequisites for this Step:
- GitHub connector configured in Harness with proper authentication. Go to GitHub Connector to learn more.
- GitHub organization access with repository creation permissions.
- Pipeline variables configured (
repo_name
,org_name
,repo_desc
)
Step Creation Instructions:
-
In the IDP stage, click + Add Step.
-
Select CreateRepo from the step library. A CreateRepo step is used to create a repository with the preferred Git provider. Go to Create Repo Step to learn more about its configuration.
-
Configure the step:
- Step Name:
Create Repository
- Identifier:
create_repo
- Description:
Creates a new GitHub repository with specified configuration
- Step Name:
-
Configure Repository Settings:
- Git Provider: Select
Third-party Git Provider
- Connector Type: Select
Github
- Repository Type: Select
public
(orprivate
based on your requirements) - Codebase Repo Connector: Choose your configured GitHub connector (e.g.,
account.your_github_connector
) - Organization:
<+pipeline.variables.org_name>
(since this is a user input, simply paste the variable reference here to pass the Workflow input here as a variable) - Repository:
<+pipeline.variables.repo_name>
(since this is a user input, simply paste the variable reference here to pass the Workflow input here as a variable) - Description:
<+pipeline.variables.repo_desc>
- Default Branch:
main
- Git Provider: Select
-
Advanced Settings (Optional):
- Initialize with README: Leave unchecked (we'll create our own)
- Add .gitignore: Leave unchecked (we'll create a custom one)
- Add License: Leave unchecked
- Interactive Guide
- YAML
- step:
type: CreateRepo
name: Create Repository
identifier: create_repo
spec:
connectorType: Github
connectorRef: account.your_github_connector
organization: <+pipeline.variables.org_name>
repository: <+pipeline.variables.repo_name>
repoType: public
description: <+pipeline.variables.repo_desc>
defaultBranch: main
Step 2: Create Feature Branch
Purpose: This step creates a feature branch from the main branch for initial development work and it runs a custom script to do the following:
- Retrieves the default branch information from the repository
- Gets the SHA (commit hash) of the default branch
- Creates a new feature branch pointing to the same commit
- Provides a dedicated branch for initial file commits
Prerequisites for this Step:
- Previous steps completed successfully
- GitHub PAT token with
repo
permissions. Go to GitHub PAT to learn more. - Pipeline variables configured (
repo_branch_name
,org_name
,repo_name
,token
)
Step Creation Instructions:
-
Add the Step:
- Click + Add Step after the
CreateRepo
step - Select Run from the step library. A Run step is used here run scripts in a Pipeline. Go to Run Step Settings to learn more about the same.
- Click + Add Step after the
-
Configure Basic Settings:
- Step Name:
Create Feature Branch
- Identifier:
create_branch
- Description:
Creates a feature branch for initial development
- Step Name:
-
Configure Container Settings: Container Registry and Image ensure that the build environment has the binaries necessary to execute the commands that you want to run in this step. Go to Container Registry and Image to learn more.
- Container Registry: Select your container registry connector (e.g.,
account.harnessImage
) - Image:
node:18
(providescurl
andbash
utilities) - Shell:
Bash
- Container Registry: Select your container registry connector (e.g.,
-
Configure the Script: This script automates the creation of a feature branch from the
main
branch using GitHub's REST API. Here's what it does:- Validates inputs: Ensures all required variables (branch name, owner, repo, token) are provided
- Retrieves default branch: Gets the repository's default branch name (main/master)
- Gets branch SHA: Fetches the commit hash of the default branch
- Creates new branch: Uses GitHub API to create a new branch pointing to the same commit
- Provides feedback: Confirms successful branch creation
Feature Branch Creation Script
set -e
BRANCH_NAME=<+pipeline.variables.repo_branch_name>
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
if [ -z "$BRANCH_NAME" ] || [ -z "$OWNER" ] || [ -z "$REPO" ] || [ -z "$TOKEN" ]; then
echo "Usage: $0 <branch_name> <owner> <repo> <github_token>"
exit 1
fi
# Get the default branch (main/master)
BASE_BRANCH=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO" | grep '"default_branch":' | sed -E 's/.*"([^"]+)".*/\1/')
# Get SHA of default branch
SHA=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO/git/ref/heads/$BASE_BRANCH" | grep '"sha":' | head -n 1 | sed -E 's/.*"([^"]+)".*/\1/')
# Create the new branch
curl -s -X POST -H "Authorization: token $TOKEN" \
-d "{\"ref\":\"refs/heads/$BRANCH_NAME\",\"sha\":\"$SHA\"}" \
"https://api.github.com/repos/$OWNER/$REPO/git/refs"
echo "✅ Branch '$BRANCH_NAME' created in $OWNER/$REPO"
- Interactive Guide
- YAML
- step:
type: Run
name: Create Feature Branch
identifier: create_branch
spec:
connectorRef: account.harnessImage
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
BRANCH_NAME=<+pipeline.variables.repo_branch_name>
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
echo "🌿 Creating branch '$BRANCH_NAME' in $OWNER/$REPO"
# Get the default branch SHA
BASE_BRANCH=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO" | \
grep '"default_branch":' | sed -E 's/.*"([^"]+)".*/\1/')
# Get SHA of default branch
SHA=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO/git/ref/heads/$BASE_BRANCH" | \
grep '"sha":' | head -n 1 | sed -E 's/.*"([^"]+)".*/\1/')
# Create the new branch
curl -s -X POST -H "Authorization: token $TOKEN" \
-d "{\"ref\":\"refs/heads/$BRANCH_NAME\",\"sha\":\"$SHA\"}" \
"https://api.github.com/repos/$OWNER/$REPO/git/refs"
echo "✅ Branch '$BRANCH_NAME' created successfully!"
Step 3: Create Directory
Purpose: This step creates a project directory structure for organizing files before pushing to the repository.
- Creates a directory with the repository name
- Provides a workspace for file generation
- Prepares the structure for the
DirectPush
step
Prerequisites for this Step:
- Previous steps completed successfully
- Pipeline variables configured (
repo_name
)
Step Creation Instructions:
-
Add the Step:
- Click + Add Step after the Create Feature Branch step
- Select Run from the step library
-
Configure Basic Settings:
- Step Name:
Create Directory
- Identifier:
create_directory
- Description:
Creates project directory structure
- Step Name:
-
Configure Container Settings:
- Container Registry: Select your container registry connector
- Image:
node:18
- Shell:
Sh
(simple shell commands)
-
Configure the Script:
mkdir <+pipeline.variables.repo_name>
ls -la
echo "📁 Directory '<+pipeline.variables.repo_name>' created successfully"
- Interactive Guide
- YAML
- step:
type: Run
name: Create Directory
identifier: create_directory
spec:
connectorRef: account.harnessImage
image: node:18
shell: Sh
command: |-
mkdir -p <+pipeline.variables.repo_name>
ls -la
echo "📁 Directory '<+pipeline.variables.repo_name>' created successfully"
Step 4: Generate Project Files
Purpose: This step creates standard project files to provide a consistent starting point for all repositories, it runs a custom script to do the following:
- Creates a comprehensive
README.md
with project information - Generates a
demo.yaml
configuration file with project metadata - Creates a thorough
.gitignore
file covering common development artifacts - Provides a consistent starting point for all repositories
Prerequisites for this Step:
- Directory created (Step 3 completed)
- Pipeline variables configured (
repo_name
,repo_branch_name
)
Step Creation Instructions:
-
Add the Step:
- Click + Add Step after the Create Directory step
- Select Run from the step library
-
Configure Basic Settings:
- Step Name:
Generate Project Files
- Identifier:
generate_files
- Description:
Creates standard project files (README, .gitignore, demo.yaml)
- Step Name:
-
Configure Container Settings:
- Container Registry: Select your container registry connector
- Image:
node:18
- Shell:
Bash
-
Configure the Script:
This script creates three essential project files that provide a standardized foundation for every repository. Here's what each part does:
Script Overview:
- Sets up error handling with
set -e
to exit on any command failure - Creates README.md with project documentation template
- Generates demo.yaml with project metadata and feature flags
- Creates comprehensive .gitignore covering multiple development environments
- Provides feedback on successful file creation
Complete Script
Complete Project Files Generation Script
#!/bin/bash
set -e
REPO_NAME=<+pipeline.variables.repo_name>
echo "📝 Creating project files for $REPO_NAME"
# Create README.md
cat > $REPO_NAME/README.md << EOF
# $REPO_NAME
This repository was created using Harness IDP workflow.
## Getting Started
Add your project documentation here.
## Development
1. Clone the repository
2. Switch to the feature branch: \`git checkout <+pipeline.variables.repo_branch_name>\`
3. Start developing your project
## Contributing
1. Create a feature branch
2. Make your changes
3. Submit a pull request
EOF
# Create demo.yaml
cat > $REPO_NAME/demo.yaml << EOF
# Demo configuration file
project:
name: $REPO_NAME
version: "1.0.0"
created_by: "Harness IDP Workflow"
created_date: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
settings:
environment: "development"
debug: true
features:
- name: "automated_setup"
enabled: true
- name: "branch_protection"
enabled: true
- name: "webhook_integration"
enabled: true
EOF
# Create .gitignore
cat > $REPO_NAME/.gitignore << EOF
# Dependencies
node_modules/
vendor/
# Build outputs
dist/
build/
target/
out/
# Environment files
.env
.env.local
.env.production
.env.staging
# IDE files
.vscode/
.idea/
*.swp
*.swo
*~
# OS files
.DS_Store
Thumbs.db
desktop.ini
# Logs
*.log
logs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
EOF
echo "✅ Project files created successfully!"
echo "📋 Files created:"
ls -la $REPO_NAME/
Script Breakdown:
1. Environment Setup & Variables:
#!/bin/bash
set -e
REPO_NAME=<+pipeline.variables.repo_name>
echo "📝 Creating project files for $REPO_NAME"
- Sets bash error handling to exit on failures
- Gets repository name from pipeline variables
2. README.md Creation:
- Creates a comprehensive README with project name
- Includes getting started instructions
README.md Creation Script
# Create README.md
cat > $REPO_NAME/README.md << EOF
# $REPO_NAME
This repository was created using Harness IDP workflow.
## Getting Started
Add your project documentation here.
## Development
1. Clone the repository
2. Switch to the feature branch: \`git checkout <+pipeline.variables.repo_branch_name>\`
3. Start developing your project
## Contributing
1. Create a feature branch
2. Make your changes
3. Submit a pull request
EOF
3. Demo Configuration File:
- Creates a YAML configuration file with project metadata
- Includes timestamp of creation
- Documents the automated features enabled
Demo Configuration Creation Script
# Create demo.yaml
cat > $REPO_NAME/demo.yaml << EOF
# Demo configuration file
project:
name: $REPO_NAME
version: "1.0.0"
created_by: "Harness IDP Workflow"
created_date: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
settings:
environment: "development"
debug: true
features:
- name: "automated_setup"
enabled: true
- name: "branch_protection"
enabled: true
- name: "webhook_integration"
enabled: true
EOF
4. Comprehensive .gitignore:
- Covers common dependency directories (Node.js, PHP, etc.)
- Excludes build artifacts and compiled outputs
- Ignores environment and configuration files
- Excludes IDE-specific files and temporary files
- Handles OS-specific files (macOS, Windows)
- Covers logging and runtime data
- Includes coverage reports and package manager files
.gitignore Creation Script
# Create .gitignore
cat > $REPO_NAME/.gitignore << EOF
# Dependencies
node_modules/
vendor/
# Build outputs
dist/
build/
target/
out/
# Environment files
.env
.env.local
.env.production
.env.staging
# IDE files
.vscode/
.idea/
*.swp
*.swo
*~
# OS files
.DS_Store
Thumbs.db
desktop.ini
# Logs
*.log
logs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
EOF
5. Success Confirmation:
echo "✅ Project files created successfully!"
echo "📋 Files created:"
ls -la $REPO_NAME/
- Interactive Guide
- YAML
- step:
type: Run
name: Generate Project Files
identifier: generate_files
spec:
connectorRef: account.harnessImage
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
REPO_NAME=<+pipeline.variables.repo_name>
echo "📝 Creating project files for $REPO_NAME"
# Create README.md
cat > $REPO_NAME/README.md << EOF
# $REPO_NAME
This repository was created using Harness IDP workflow.
## Getting Started
Add your project documentation here.
## Development
1. Clone the repository
2. Switch to the feature branch: \`git checkout <+pipeline.variables.repo_branch_name>\`
3. Start developing your project
## Contributing
1. Create a feature branch
2. Make your changes
3. Submit a pull request
EOF
# Create demo.yaml
cat > $REPO_NAME/demo.yaml << EOF
# Demo configuration file
project:
name: $REPO_NAME
version: "1.0.0"
created_by: "Harness IDP Workflow"
created_date: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
settings:
environment: "development"
debug: true
features:
- name: "automated_setup"
enabled: true
- name: "branch_protection"
enabled: true
- name: "webhook_integration"
enabled: true
EOF
# Create .gitignore
cat > $REPO_NAME/.gitignore << EOF
# Dependencies
node_modules/
vendor/
# Build outputs
dist/
build/
target/
out/
# Environment files
.env
.env.local
.env.production
.env.staging
# IDE files
.vscode/
.idea/
*.swp
*.swo
*~
# OS files
.DS_Store
Thumbs.db
desktop.ini
# Logs
*.log
logs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
EOF
echo "✅ Project files created successfully!"
echo "📋 Files created:"
ls -la $REPO_NAME/
Step 5: Push Files to Repository
Purpose: This step commits and pushes the generated files to the feature branch in the GitHub repository.
- Commits all generated files to the feature branch
- Pushes the initial project structure to GitHub
- Makes the files available in the repository for development
- Preserves the
main
branch for branch protection setup
Prerequisites for this Step:
- Project files generated (Step 4 completed)
- GitHub connector with
push
permissions. Go to GitHub Connector to learn more. - Pipeline variables configured (
org_name
,repo_name
,repo_branch_name
)
Step Creation Instructions:
-
Add the Step:
- Click + Add Step after the Generate Project Files step
- Select DirectPush from the step library under "Git Repository Setup". This step will push all the generated files to the new feature branch. Go to Direct Push Step to learn more.
-
Configure Basic Settings:
- Step Name:
Push Files to Repository
- Identifier:
push_files
- Description:
Commits and pushes generated files to the feature branch
- Step Name:
-
Configure Push Settings:
- Connector Type: Select
Github
- Connector Reference: Choose your GitHub connector
- Organization:
<+pipeline.variables.org_name>
- Repository:
<+pipeline.variables.repo_name>
- Code Directory:
<+pipeline.variables.repo_name>
(the directory containing the files) - Branch:
<+pipeline.variables.repo_branch_name>
(push tofeature branch
, notmain
)
- Connector Type: Select
-
Advanced Settings:
- Force Push: Leave unchecked (false)
- Commit Message: You can customize or leave default
- Interactive Guide
- YAML
- step:
type: DirectPush
name: Push Files to Repository
identifier: push_files
spec:
connectorType: Github
forcePush: false
connectorRef: account.your_github_connector
organization: <+pipeline.variables.org_name>
repository: <+pipeline.variables.repo_name>
codeDirectory: <+pipeline.variables.repo_name>
branch: <+pipeline.variables.repo_branch_name>
Step 6: Configure Branch Protection
Purpose: This step applies security rules to the main branch to enforce code review and CI/CD requirements.
- Protects the
main
branch from direct pushes - Requires status checks to pass before merging
- Enforces pull request reviews (1 approval required)
- Requires code owner reviews when applicable
- Applies rules to all users including administrators
Prerequisites for this Step:
- Repository created with files pushed (Steps 1-5 completed)
- GitHub PAT token with
admin:repo_hook
permissions - Pipeline variables configured (org_name, repo_name, token)
Step Creation Instructions:
-
Add the Step:
- Click + Add Step after the Push Files step.
- Select Run from the step library.
-
Configure Basic Settings:
- Step Name:
Configure Branch Protection
- Identifier:
branch_protection
- Description:
Sets up branch protection rules on the main branch
- Step Name:
-
Configure Container Settings:
- Container Registry: Select your container registry connector
- Image:
node:18
- Shell:
Bash
-
Configure the Script: This script configures branch protection rules on the
main
branch using GitHub's REST API to enforce security and code quality standards. Here's what each part does:
Script Overview:
- Sets up error handling with
set -e
to exit on any command failure - Retrieves default branch information from the repository
- Applies comprehensive protection rules via GitHub API
- Validates successful configuration with HTTP status code checking
Complete Script:
Complete Branch Protection Script
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
echo "🛡️ Setting up branch protection for $OWNER/$REPO"
# Get the default branch to protect
BASE_BRANCH=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO" | \
grep '"default_branch":' | sed -E 's/.*"([^"]+)".*/\1/')
echo "🔒 Protecting branch: $BASE_BRANCH"
# Set branch protection with proper JSON formatting
RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X PUT \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/branches/$BASE_BRANCH/protection" \
-d '{
"required_status_checks": {
"strict": true,
"contexts": ["ci/build", "ci/test"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true,
"required_approving_review_count": 1
},
"restrictions": null
}')
# Extract HTTP status code
HTTP_CODE=$(echo "$RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
if [ "$HTTP_CODE" = "200" ]; then
echo "✅ Branch protection configured successfully!"
echo "🔐 Protection rules applied:"
echo " - Required status checks: ci/build, ci/test"
echo " - Required PR reviews: 1 approval"
echo " - Dismiss stale reviews: enabled"
echo " - Code owner reviews: required"
echo " - Admin enforcement: enabled"
else
echo "❌ Failed to configure branch protection (HTTP $HTTP_CODE)"
echo "Response: $(echo "$RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')"
exit 1
fi
Script Breakdown:
1. Environment Setup & Variables:
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
echo "🛡️ Setting up branch protection for $OWNER/$REPO"
- Sets bash error handling to exit on failures
- Gets organization, repository name, and GitHub token from pipeline variables
2. Default Branch Detection:
# Get the default branch to protect
BASE_BRANCH=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO" | \
grep '"default_branch":' | sed -E 's/.*"([^"]+)".*/\1/')
echo "🔒 Protecting branch: $BASE_BRANCH"
- Queries GitHub API to get repository information
- Extracts the default branch name (usually
main
ormaster
) - Confirms which branch will be protected
3. Branch Protection Configuration:
- Required Status Checks: Enforces CI/CD pipeline success before merging
strict: true
- Requires branches to be up-to-date before mergingcontexts: ["ci/build", "ci/test"]
- Specific checks that must pass
- Admin Enforcement: Rules apply to repository administrators too
- Pull Request Reviews: Mandatory code review process
dismiss_stale_reviews: true
- Invalidates approvals when new commits are addedrequire_code_owner_reviews: true
- Requires approval from code ownersrequired_approving_review_count: 1
- Minimum number of approvals needed
- Restrictions: Set to
null
(no user/team restrictions)
Protection Rules API Call
# Set branch protection with proper JSON formatting
RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X PUT \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/branches/$BASE_BRANCH/protection" \
-d '{
"required_status_checks": {
"strict": true,
"contexts": ["ci/build", "ci/test"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true,
"required_approving_review_count": 1
},
"restrictions": null
}')
4. Response Validation & Feedback:
- Extracts HTTP status code from the API response
- Success (200): Confirms protection rules and lists applied settings
- Failure (non-200): Shows error details and exits with error code
Response Validation Script
# Extract HTTP status code
HTTP_CODE=$(echo "$RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
if [ "$HTTP_CODE" = "200" ]; then
echo "✅ Branch protection configured successfully!"
echo "🔐 Protection rules applied:"
echo " - Required status checks: ci/build, ci/test"
echo " - Required PR reviews: 1 approval"
echo " - Dismiss stale reviews: enabled"
echo " - Code owner reviews: required"
echo " - Admin enforcement: enabled"
else
echo "❌ Failed to configure branch protection (HTTP $HTTP_CODE)"
echo "Response: $(echo "$RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')"
exit 1
fi
- Interactive Guide
- YAML
- step:
type: Run
name: Configure Branch Protection
identifier: branch_protection
spec:
connectorRef: account.harnessImage
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
echo "🛡️ Setting up branch protection for $OWNER/$REPO"
# Get the default branch to protect
BASE_BRANCH=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO" | \
grep '"default_branch":' | sed -E 's/.*"([^"]+)".*/\1/')
echo "🔒 Protecting branch: $BASE_BRANCH"
# Set branch protection with proper JSON formatting
RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X PUT \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/branches/$BASE_BRANCH/protection" \
-d '{
"required_status_checks": {
"strict": true,
"contexts": ["ci/build", "ci/test"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true,
"required_approving_review_count": 1
},
"restrictions": null
}')
# Extract HTTP status code
HTTP_CODE=$(echo "$RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
if [ "$HTTP_CODE" = "200" ]; then
echo "✅ Branch protection configured successfully!"
echo "🔐 Protection rules applied:"
echo " - Required status checks: ci/build, ci/test"
echo " - Required PR reviews: 1 approval"
echo " - Dismiss stale reviews: enabled"
echo " - Code owner reviews: required"
echo " - Admin enforcement: enabled"
else
echo "❌ Failed to configure branch protection (HTTP $HTTP_CODE)"
echo "Response: $(echo "$RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')"
exit 1
fi
Step 7: Setup Webhook
Purpose: This step configures a webhook to trigger CI/CD pipelines when code changes occur in the repository.
- Verifies the repository is accessible and ready
- Creates a webhook with comprehensive event coverage
- Configures secure JSON payload delivery
- Enables automatic CI/CD pipeline triggering
Prerequisites for this Step:
- Repository fully configured (Steps 1-6 completed)
- GitHub PAT token with
admin:repo_hook
permissions - Pipeline variables configured (
org_name
,repo_name
,token
,webhook_url
) - Valid webhook URL endpoint
Ensure that the webhook_url
variable is configured as a fixed value in the pipeline variables definition.
Step Creation Instructions:
-
Add the Step:
- Click + Add Step after the Configure Branch Protection step
- Select Run from the step library
-
Configure Basic Settings:
- Step Name:
Setup Webhook
- Identifier:
setup_webhook
- Description:
Configures webhook for CI/CD pipeline integration
- Step Name:
-
Configure Container Settings:
- Container Registry: Select your container registry connector
- Image:
node:18
- Shell:
Bash
-
Configure the Script: This script configures a webhook to automatically trigger CI/CD pipelines when code changes occur in the repository. Here's what each part does:
Complete Script:
Complete Webhook Setup Script
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
WEBHOOK_URL=<+pipeline.variables.webhook_url>
echo "🔗 Setting up webhook for $OWNER/$REPO"
echo "📡 Webhook URL: $WEBHOOK_URL"
# Verify repository exists first
echo "🔍 Verifying repository exists..."
REPO_CHECK=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO")
if echo "$REPO_CHECK" | grep -q '"message": "Not Found"'; then
echo "❌ Repository not found!"
exit 1
fi
echo "✅ Repository verified"
# Add delay to ensure repo is ready
echo "⏳ Waiting for repository to be fully ready..."
sleep 5
# Create webhook with comprehensive error handling
echo "🚀 Creating webhook..."
WEBHOOK_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X POST \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/hooks" \
-d "{
\"name\": \"web\",
\"active\": true,
\"events\": [\"push\", \"pull_request\", \"release\"],
\"config\": {
\"url\": \"$WEBHOOK_URL\",
\"content_type\": \"json\",
\"insecure_ssl\": \"0\"
}
}")
# Extract HTTP status code and response body
HTTP_CODE=$(echo "$WEBHOOK_RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
RESPONSE_BODY=$(echo "$WEBHOOK_RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')
if [ "$HTTP_CODE" = "201" ]; then
WEBHOOK_ID=$(echo "$RESPONSE_BODY" | grep '"id":' | head -n 1 | sed -E 's/.*"id": ([0-9]+).*/\1/')
echo "✅ Webhook #$WEBHOOK_ID created successfully!"
echo "🎯 Configured events:"
echo " - push (all branches)"
echo " - pull_request (opened, synchronized, closed)"
echo " - release (published, edited)"
echo "🔒 Security: SSL verification enabled"
echo "📦 Content type: JSON"
else
echo "❌ Failed to create webhook (HTTP $HTTP_CODE)"
echo "📝 Response details:"
echo "$RESPONSE_BODY" | head -10
# Provide troubleshooting hints
if [ "$HTTP_CODE" = "422" ]; then
echo "💡 Troubleshooting: Check if webhook URL is valid and accessible"
elif [ "$HTTP_CODE" = "404" ]; then
echo "💡 Troubleshooting: Verify repository exists and token has correct permissions"
elif [ "$HTTP_CODE" = "403" ]; then
echo "💡 Troubleshooting: Token may lack admin:repo_hook permissions"
fi
exit 1
fi
Script Breakdown:
1. Environment Setup & Variables:
- Sets bash error handling to exit on failures
- Gets all required variables from pipeline configuration
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
WEBHOOK_URL=<+pipeline.variables.webhook_url>
echo "🔗 Setting up webhook for $OWNER/$REPO"
echo "📡 Webhook URL: $WEBHOOK_URL"
2. Repository Verification:
- Queries GitHub API to confirm repository exists
- Exits with error if repository is not found
- Ensures webhook creation won't fail due to missing repository
# Verify repository exists first
echo "🔍 Verifying repository exists..."
REPO_CHECK=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO")
if echo "$REPO_CHECK" | grep -q '"message": "Not Found"'; then
echo "❌ Repository not found!"
exit 1
fi
echo "✅ Repository verified"
3. Webhook Creation: Webhook Configuration Details:
- Events Monitored:
push
,pull_request
,release
- Content Type: JSON for structured payload delivery
- Security: SSL verification enabled (
insecure_ssl: "0"
) - Status: Active webhook ready to trigger immediately
Webhook Configuration API Call
# Create webhook with comprehensive error handling
echo "🚀 Creating webhook..."
WEBHOOK_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X POST \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/hooks" \
-d "{
\"name\": \"web\",
\"active\": true,
\"events\": [\"push\", \"pull_request\", \"release\"],
\"config\": {
\"url\": \"$WEBHOOK_URL\",
\"content_type\": \"json\",
\"insecure_ssl\": \"0\"
}
}")
4. Response Validation & Feedback:
- Success (201): Extracts webhook ID and confirms configuration
- Failure (non-201): Provides specific troubleshooting guidance based on HTTP status code
- Error Codes:
422
: Invalid webhook URL or configuration404
: Repository not found or insufficient permissions403
: Token lacks required webhook permissions
Response Handling Script
# Extract HTTP status code and response body
HTTP_CODE=$(echo "$WEBHOOK_RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
RESPONSE_BODY=$(echo "$WEBHOOK_RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')
if [ "$HTTP_CODE" = "201" ]; then
WEBHOOK_ID=$(echo "$RESPONSE_BODY" | grep '"id":' | head -n 1 | sed -E 's/.*"id": ([0-9]+).*/\1/')
echo "✅ Webhook #$WEBHOOK_ID created successfully!"
echo "🎯 Configured events:"
echo " - push (all branches)"
echo " - pull_request (opened, synchronized, closed)"
echo " - release (published, edited)"
echo "🔒 Security: SSL verification enabled"
echo "📦 Content type: JSON"
else
echo "❌ Failed to create webhook (HTTP $HTTP_CODE)"
echo "📝 Response details:"
echo "$RESPONSE_BODY" | head -10
# Provide troubleshooting hints
if [ "$HTTP_CODE" = "422" ]; then
echo "💡 Troubleshooting: Check if webhook URL is valid and accessible"
elif [ "$HTTP_CODE" = "404" ]; then
echo "💡 Troubleshooting: Verify repository exists and token has correct permissions"
elif [ "$HTTP_CODE" = "403" ]; then
echo "💡 Troubleshooting: Token may lack admin:repo_hook permissions"
fi
exit 1
fi
Webhook Setup Pipeline Step YAML
- step:
type: Run
name: Setup Webhook
identifier: setup_webhook
spec:
connectorRef: account.harnessImage
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
WEBHOOK_URL=<+pipeline.variables.webhook_url>
echo "🔗 Setting up webhook for $OWNER/$REPO"
echo "📡 Webhook URL: $WEBHOOK_URL"
# Verify repository exists first
echo "🔍 Verifying repository exists..."
REPO_CHECK=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO")
if echo "$REPO_CHECK" | grep -q '"message": "Not Found"'; then
echo "❌ Repository not found!"
exit 1
fi
echo "✅ Repository verified"
# Add delay to ensure repo is ready
echo "⏳ Waiting for repository to be fully ready..."
sleep 5
# Create webhook with comprehensive error handling
echo "🚀 Creating webhook..."
WEBHOOK_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X POST \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/hooks" \
-d "{
\"name\": \"web\",
\"active\": true,
\"events\": [\"push\", \"pull_request\", \"release\"],
\"config\": {
\"url\": \"$WEBHOOK_URL\",
\"content_type\": \"json\",
\"insecure_ssl\": \"0\"
}
}")
# Extract HTTP status code and response body
HTTP_CODE=$(echo "$WEBHOOK_RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
RESPONSE_BODY=$(echo "$WEBHOOK_RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')
if [ "$HTTP_CODE" = "201" ]; then
WEBHOOK_ID=$(echo "$RESPONSE_BODY" | grep '"id":' | head -n 1 | sed -E 's/.*"id": ([0-9]+).*/\1/')
echo "✅ Webhook #$WEBHOOK_ID created successfully!"
echo "🎯 Configured events:"
echo " - push (all branches)"
echo " - pull_request (opened, synchronized, closed)"
echo " - release (published, edited)"
echo "🔒 Security: SSL verification enabled"
echo "📦 Content type: JSON"
else
echo "❌ Failed to create webhook (HTTP $HTTP_CODE)"
echo "📝 Response details:"
echo "$RESPONSE_BODY" | head -10
# Provide troubleshooting hints
if [ "$HTTP_CODE" = "422" ]; then
echo "💡 Troubleshooting: Check if webhook URL is valid and accessible"
elif [ "$HTTP_CODE" = "404" ]; then
echo "💡 Troubleshooting: Verify repository exists and token has correct permissions"
elif [ "$HTTP_CODE" = "403" ]; then
echo "💡 Troubleshooting: Token may lack admin:repo_hook permissions"
fi
exit 1
fi
Pipeline YAML Configuration
Below is the complete pipeline YAML configuration that you can copy and paste directly into your Harness pipeline. Make sure to replace the placeholder values with your specific configuration details.
Pipeline YAML Configuration
pipeline:
name: GitHub Repository Onboarding
identifier: github_repo_onboarding
projectIdentifier: <YOUR_PROJECT_ID>
orgIdentifier: <YOUR_ORG_ID>
tags: {}
stages:
- stage:
name: Repository Setup
identifier: repository_setup
description: "Automated GitHub repository creation and configuration"
type: IDP
spec:
execution:
steps:
# Step 1: Create Repository
- step:
type: CreateRepo
name: Create Repository
identifier: create_repo
spec:
connectorType: Github
connectorRef: <YOUR_GITHUB_CONNECTOR>
organization: <+pipeline.variables.org_name>
repository: <+pipeline.variables.repo_name>
repoType: public
description: <+pipeline.variables.repo_desc>
defaultBranch: main
# Step 2: Create Feature Branch
- step:
type: Run
name: Create Feature Branch
identifier: create_branch
spec:
connectorRef: <YOUR_CONTAINER_REGISTRY_CONNECTOR>
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
BRANCH_NAME=<+pipeline.variables.repo_branch_name>
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
if [ -z "$BRANCH_NAME" ] || [ -z "$OWNER" ] || [ -z "$REPO" ] || [ -z "$TOKEN" ]; then
echo "Usage: $0 <branch_name> <owner> <repo> <github_token>"
exit 1
fi
# Get the default branch (main/master)
BASE_BRANCH=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO" | grep '"default_branch":' | sed -E 's/.*"([^"]+)".*/\1/')
# Get SHA of default branch
SHA=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO/git/ref/heads/$BASE_BRANCH" | grep '"sha":' | head -n 1 | sed -E 's/.*"([^"]+)".*/\1/')
# Create the new branch
curl -s -X POST -H "Authorization: token $TOKEN" \
-d "{\"ref\":\"refs/heads/$BRANCH_NAME\",\"sha\":\"$SHA\"}" \
"https://api.github.com/repos/$OWNER/$REPO/git/refs"
echo "✅ Branch '$BRANCH_NAME' created in $OWNER/$REPO"
# Step 3: Create Directory
- step:
type: Run
name: Create Directory
identifier: create_directory
spec:
connectorRef: <YOUR_CONTAINER_REGISTRY_CONNECTOR>
image: node:18
shell: Sh
command: |-
mkdir -p <+pipeline.variables.repo_name>
ls -la
echo "📁 Directory '<+pipeline.variables.repo_name>' created successfully"
# Step 4: Generate Project Files
- step:
type: Run
name: Generate Project Files
identifier: generate_files
spec:
connectorRef: <YOUR_CONTAINER_REGISTRY_CONNECTOR>
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
REPO_NAME=<+pipeline.variables.repo_name>
echo "📝 Creating project files for $REPO_NAME"
# Create README.md
cat > $REPO_NAME/README.md << EOF
# $REPO_NAME
This repository was created using Harness IDP workflow.
## Getting Started
Add your project documentation here.
## Development
1. Clone the repository
2. Switch to the feature branch: \`git checkout <+pipeline.variables.repo_branch_name>\`
3. Start developing your project
## Contributing
1. Create a feature branch
2. Make your changes
3. Submit a pull request
EOF
# Create demo.yaml
cat > $REPO_NAME/demo.yaml << EOF
# Demo configuration file
project:
name: $REPO_NAME
version: "1.0.0"
created_by: "Harness IDP Workflow"
created_date: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
settings:
environment: "development"
debug: true
features:
- name: "automated_setup"
enabled: true
- name: "branch_protection"
enabled: true
- name: "webhook_integration"
enabled: true
EOF
# Create .gitignore
cat > $REPO_NAME/.gitignore << EOF
# Dependencies
node_modules/
vendor/
# Build outputs
dist/
build/
target/
out/
# Environment files
.env
.env.local
.env.production
.env.staging
# IDE files
.vscode/
.idea/
*.swp
*.swo
*~
# OS files
.DS_Store
Thumbs.db
desktop.ini
# Logs
*.log
logs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
EOF
echo "✅ Project files created successfully!"
echo "📋 Files created:"
ls -la $REPO_NAME/
# Step 5: Push Files to Repository
- step:
type: DirectPush
name: Push Files to Repository
identifier: push_files
spec:
connectorType: Github
connectorRef: <YOUR_GITHUB_CONNECTOR>
organization: <+pipeline.variables.org_name>
repository: <+pipeline.variables.repo_name>
codeDirectory: <+pipeline.variables.repo_name>
branch: <+pipeline.variables.repo_branch_name>
# Step 6: Configure Branch Protection
- step:
type: Run
name: Configure Branch Protection
identifier: branch_protection
spec:
connectorRef: <YOUR_CONTAINER_REGISTRY_CONNECTOR>
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
echo "🛡️ Setting up branch protection for $OWNER/$REPO"
# Get the default branch to protect
BASE_BRANCH=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO" | \
grep '"default_branch":' | sed -E 's/.*"([^"]+)".*/\1/')
echo "🔒 Protecting branch: $BASE_BRANCH"
# Set branch protection with proper JSON formatting
RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X PUT \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/branches/$BASE_BRANCH/protection" \
-d '{
"required_status_checks": {
"strict": true,
"contexts": ["ci/build", "ci/test"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true,
"required_approving_review_count": 1
},
"restrictions": null
}')
# Extract HTTP status code
HTTP_CODE=$(echo "$RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
if [ "$HTTP_CODE" = "200" ]; then
echo "✅ Branch protection configured successfully!"
echo "🔐 Protection rules applied:"
echo " - Required status checks: ci/build, ci/test"
echo " - Required PR reviews: 1 approval"
echo " - Dismiss stale reviews: enabled"
echo " - Code owner reviews: required"
echo " - Admin enforcement: enabled"
else
echo "❌ Failed to configure branch protection (HTTP $HTTP_CODE)"
echo "Response: $(echo "$RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')"
exit 1
fi
# Step 7: Setup Webhook
- step:
type: Run
name: Setup Webhook
identifier: setup_webhook
spec:
connectorRef: <YOUR_CONTAINER_REGISTRY_CONNECTOR>
image: node:18
shell: Bash
command: |-
#!/bin/bash
set -e
OWNER=<+pipeline.variables.org_name>
REPO=<+pipeline.variables.repo_name>
TOKEN=<+pipeline.variables.token>
WEBHOOK_URL=<+pipeline.variables.webhook_url>
echo "🔗 Setting up webhook for $OWNER/$REPO"
echo "📡 Webhook URL: $WEBHOOK_URL"
# Verify repository exists first
echo "🔍 Verifying repository exists..."
REPO_CHECK=$(curl -s -H "Authorization: token $TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO")
if echo "$REPO_CHECK" | grep -q '"message": "Not Found"'; then
echo "❌ Repository not found!"
exit 1
fi
echo "✅ Repository verified"
# Add delay to ensure repo is ready
echo "⏳ Waiting for repository to be fully ready..."
sleep 5
# Create webhook with comprehensive error handling
echo "🚀 Creating webhook..."
WEBHOOK_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -X POST \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/hooks" \
-d "{
\"name\": \"web\",
\"active\": true,
\"events\": [\"push\", \"pull_request\", \"release\"],
\"config\": {
\"url\": \"$WEBHOOK_URL\",
\"content_type\": \"json\",
\"insecure_ssl\": \"0\"
}
}")
# Extract HTTP status code and response body
HTTP_CODE=$(echo "$WEBHOOK_RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
RESPONSE_BODY=$(echo "$WEBHOOK_RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')
if [ "$HTTP_CODE" = "201" ]; then
WEBHOOK_ID=$(echo "$RESPONSE_BODY" | grep '"id":' | head -n 1 | sed -E 's/.*"id": ([0-9]+).*/\1/')
echo "✅ Webhook #$WEBHOOK_ID created successfully!"
echo "🎯 Configured events:"
echo " - push (all branches)"
echo " - pull_request (opened, synchronized, closed)"
echo " - release (published, edited)"
echo "🔒 Security: SSL verification enabled"
echo "📦 Content type: JSON"
else
echo "❌ Failed to create webhook (HTTP $HTTP_CODE)"
echo "📝 Response details:"
echo "$RESPONSE_BODY" | head -10
# Provide troubleshooting hints
if [ "$HTTP_CODE" = "422" ]; then
echo "💡 Troubleshooting: Check if webhook URL is valid and accessible"
elif [ "$HTTP_CODE" = "404" ]; then
echo "💡 Troubleshooting: Verify repository exists and token has correct permissions"
elif [ "$HTTP_CODE" = "403" ]; then
echo "💡 Troubleshooting: Token may lack admin:repo_hook permissions"
fi
exit 1
fi
infrastructure:
type: KubernetesDirect
spec:
connectorRef: <YOUR_K8S_CONNECTOR>
namespace: <YOUR_NAMESPACE>
automountServiceAccountToken: true
nodeSelector: {}
os: Linux
variables:
- name: repo_name
type: String
description: "Name of the repository to create"
required: true
value: <+input>
- name: org_name
type: String
description: "GitHub organization name"
required: true
value: <+input>
- name: repo_desc
type: String
description: "Repository description"
required: true
value: <+input>
- name: repo_branch_name
type: String
description: "Feature branch name"
required: true
value: <+input>
- name: token
type: Secret
description: "GitHub personal access token"
required: true
value: <YOUR_GITHUB_TOKEN_SECRET>
- name: webhook_url
type: String
description: "Webhook URL for CI/CD integration"
required: true
value: <YOUR_WEBHOOK_URL>
Pipeline Completion
After completing all 7 steps, your pipeline will:
- ✅ Create Repository - New GitHub repo with proper configuration
- ✅ Create Feature Branch - Dedicated branch for initial development
- ✅ Create Directory - Organized workspace structure
- ✅ Generate Project Files - Standard README, .gitignore, and demo files
- ✅ Push Files - Initial project structure committed to feature branch
- ✅ Configure Branch Protection - Security rules enforced on main branch
- ✅ Setup Webhook - CI/CD integration enabled
Build the Harness IDP Workflow
Now that we have created the pipeline, we need to create the IDP Workflow that will serve as the user interface. This workflow will collect input from developers and trigger our GitHub Repository Onboarding pipeline.
Prerequisites
Before creating the workflow, ensure you have:
- Pipeline Created: The GitHub Repository Onboarding pipeline must be created and saved.
- Pipeline URL: Note down your pipeline URL for the workflow configuration.
- Harness Account Access: Permissions to create workflows in your Harness project.
- Project Details: Your account ID, organization ID, and project ID.
Workflow Overview
🔤 Inputs Required:
- Repository Information: Organization name, repository name, and description
- Branch Configuration: Feature branch name for initial development
- Authentication: Secure token handling for all Workflow requests (automatically generated)
⚡ Actions Performed:
- Pipeline Triggering: Initiates the GitHub Repository Onboarding pipeline with user inputs
- Parameter Mapping: Converts form inputs to pipeline variables seamlessly
📊 Outputs Provided:
- Execution Tracking: Direct link to monitor pipeline progress in real-time
- Status Updates: Immediate feedback on workflow submission and pipeline initiation
Creating the Workflow
Step 1: Navigate to IDP Workflows
- Go to Harness IDP in your Harness account
- Navigate to Workflows in the left sidebar
- Click "Create Workflow" to start creating a new workflow
Step 2: Configure Basic Workflow Settings
- Workflow Name:
GitHub Repository Onboarding
- Identifier:
GitHub_Repository_Onboarding
- Description:
Self-service workflow for creating GitHub repositories with automated setup
- Owner: Set to your username or team
Step 3: Configure the Workflow YAML
Use the following YAML configuration for your workflow:
apiVersion: harness.io/v1
kind: Workflow
name: GitHub Repository Onboarding
identifier: GitHub_Repository_Onboarding
type: workflow
owner: khushi
metadata: {}
spec:
output:
links:
- title: Pipeline Details
url: ${{ steps.trigger.output.PipelineUrl }}
lifecycle: production
parameters:
- title: Repository Details
required:
- orgName
- repoName
- branchName
properties:
token:
title: Harness Token
type: string
ui:widget: password
ui:field: HarnessAuthToken
orgName:
title: GitHub Organization (Owner)
type: string
description: Mention the owner username
repoName:
title: Repository Name
type: string
description: Mention the repository name to be created
repoDesc:
title: Repository Description
type: string
description: Mention the repository description
branchName:
title: Branch Name
type: string
description: Mention the branch name to be created
steps:
- id: trigger
name: Creating your new repository
action: trigger:harness-custom-pipeline
input:
url: <PIPELINE-URL>
inputset:
org_name: ${{ parameters.orgName }}
repo_name: ${{ parameters.repoName }}
repo_desc: ${{ parameters.repoDesc }}
repo_branch_name: ${{ parameters.branchName }}
apikey: ${{ parameters.token }}
Understanding the Workflow Configuration
1️⃣ Input Parameters Section
The parameters
section in the Workflow YAML defines the form fields that developers will fill out:
Required Fields:
- orgName: GitHub organization where the repository will be created.
- repoName: Name of the new repository.
- branchName: Initial feature branch name.
Optional Fields:
- repoDesc: Description for the repository
Authentication:
- token: Harness API token for pipeline execution (automatically handled)
2️⃣ Steps Section
The Workflow contains one main step:
trigger Step:
- Purpose: Triggers the GitHub Repository Onboarding pipeline
- Action:
trigger:harness-custom-pipeline
- Input Mapping: Maps input form parameters to pipeline variables
3️⃣ Output Section
Pipeline Details Link:
- Provides a direct link to view the pipeline execution
Workflow YAML Configuration
Workflow YAML Configuration
apiVersion: harness.io/v1
kind: Workflow
name: GitHub Repository Onboarding
identifier: GitHub_Repository_Onboarding
type: workflow
owner: khushi
metadata: {}
spec:
output:
links:
- title: Pipeline Details
url: ${{ steps.trigger.output.PipelineUrl }}
lifecycle: production
parameters:
- title: Repository Details
required:
- orgName
- repoName
- branchName
properties:
token:
title: Harness Token
type: string
ui:widget: password
ui:field: HarnessAuthToken
orgName:
title: GitHub Organization (Owner)
type: string
description: Mention the owner username
repoName:
title: Repository Name
type: string
description: Mention the repository name to be created
repoDesc:
title: Repository Description
type: string
description: Mention the repository description
branchName:
title: Branch Name
type: string
description: Mention the branch name to be created
steps:
- id: trigger
name: Creating your new repository
action: trigger:harness-custom-pipeline
input:
url: <PIPELINE-URL>
inputset:
org_name: ${{ parameters.orgName }}
repo_name: ${{ parameters.repoName }}
repo_desc: ${{ parameters.repoDesc }}
repo_branch_name: ${{ parameters.branchName }}
apikey: ${{ parameters.token }}
Tutorial Outcome
This tutorial creates a complete self-service GitHub repository onboarding system. Here's what happens when a developer uses your workflow:
🚀 Developer Experience (In a Nutshell)
- Developer Action: Fills out a simple form in Harness IDP with repository details
- Workflow Execution: Submits the form and receives immediate confirmation
- Pipeline Automation: 7-step pipeline executes automatically in the background
- Repository Ready: Fully configured repository appears in your GitHub organization
Automated Outcomes in Your GitHub Organization
When the pipeline completes successfully, the following will be automatically created and configured in your GitHub organization:
Repository Structure:
- ✅ New GitHub repository with the specified name and description
- ✅ Feature branch created for initial development work
- ✅ Standard project files generated and committed:
README.md
with project documentation templatedemo.yaml
with project metadata and configuration.gitignore
with comprehensive exclusion rules
Security Configuration:
- ✅ Branch protection rules applied to the main branch:
- Requires pull request reviews (1 approval minimum)
- Dismisses stale reviews when new commits are added
- Requires code owner reviews when applicable
- Enforces status checks (ci/build, ci/test) before merging
- Applies rules to administrators as well
CI/CD Integration:
- ✅ Webhook configured for automated pipeline triggering:
- Monitors
push
,pull_request
andrelease
events - Sends JSON payloads to your specified webhook URL
- Monitors
End Result
Developers can now create production-ready repositories in minutes instead of hours, with all security and CI/CD configurations applied automatically. The platform team maintains control over standards while enabling developer self-service at scale.