devops-tooling

v2026.09.24

Git operations, shell scripting, CI/CD pipelines, and terminal automation. Use for conventional commits, PowerShell/Bash scripting, configuring GitHub Actions, or automating development tooling workflows.

GitHub
安装命令
npx skhub add practicalswan/devops-tooling
Markdown
SKILL.md

Devops Tooling

Comprehensive toolkit for Git workflows, shell scripting, and development automation.

  • Leverage native parallel subagent dispatch and 200k+ context windows where available.

When to Use This Skill

Use symptom -> action triggers: when one matches, apply this skill and verify with the protocol below.

  • Creating conventional commits and managing Git workflows
  • Writing Bash, Zsh, or PowerShell automation scripts
  • Configuring CI/CD pipelines (GitHub Actions, Azure DevOps)
  • Automating development, testing, or deployment tasks
  • Troubleshooting Git conflicts and repository hygiene issues

Part 1: Git Workflows

Conventional Commits

The conventional commit specification provides an easy-to-extend set of rules for creating an explicit commit history.

Commit Format

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Types

TypePurposeExample
featNew featurefeat(auth): add OAuth2 support
fixBug fixfix(api): resolve null reference
docsDocumentation onlydocs(readme): update setup guide
styleFormatting/style (no logic)style(ui): fix indentation
refactorRefactor production coderefactor(svc): extract helpers
perfPerformance improvementperf(db): add index on email
testAdding teststest(auth): add unit tests
buildBuild system or depsbuild(ci): upgrade Node to v20
ciCI configuration changesci(github): add workflow for PRs
choreMaintenance taskschore(deps): update packages
revertRevert previous commitrevert: feat(login)

Breaking Changes

Breaking changes must be indicated by ! after the type/scope, or via BREAKING CHANGE in footer:



feat(api)!: remove deprecated v1 endpoint


feat(api): remove deprecated v1 endpoint

BREAKING CHANGE: v1 endpoints are no longer supported. Use v2.

Good Examples



feat(auth): implement JWT refresh tokens


fix(ui): resolve mobile navigation overlap issue


docs(api): add authentication examples


refactor(user): extract validation logic to separate module


perf(images): implement lazy loading


feat(core)!: change data structure from array to object

Git Operations

Branch Management



git checkout -b feature/PROJ-123/user-auth


git checkout develop


git branch -d feature/PROJ-123/user-auth


git push origin --delete feature/PROJ-123/user-auth


git branch -m new-name


git branch -a

Commit Workflow



git add .


git add file1.ts file2.ts


git add -i


git commit -m "feat(auth): add OAuth2 support"


git commit --amend


git log --oneline --graph --all


git show <commit-hash>

Merge & Rebase



git merge feature/new-feature


git rebase develop


git rebase -i HEAD~3


git rebase --abort
git merge --abort


git rebase --continue
git merge --continue

Handling Conflicts



git status


vim conflicting-file.ts


git add conflicting-file.ts


git commit  # for merges
git rebase --continue  # for rebases

Stashing



git stash push -m "Work in progress"


git stash pop


git stash apply stash@{2}


git stash list


git stash drop stash@{2}


git stash clear

Tagging



git tag -a v1.0.0 -m "Release v1.0.0"


git tag v1.0.0


git tag


git push origin --tags


git push origin v1.0.0


git tag -d v1.0.0


git push origin --delete v1.0.0

Git Diff



git diff


git diff --staged


git diff src/app.ts


git diff HEAD~2 HEAD


git log --oneline v1.0.0..v2.0.0


git diff --stat

Git Configuration



git config --global user.name "Your Name"
git config --global user.email "your@email.com"


git config --global init.defaultBranch main


git config --global commit.gpgsign true


git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status


git config --unset user.name


git config --list

Part 2: Shell Scripting (bash/zsh)

General Principles

  • Generate clean, simple, and concise code
  • Ensure scripts are easily readable and understandable
  • Add comments where needed for understanding
  • Generate concise echo outputs for execution status
  • Avoid unnecessary output and excessive logging

Error Handling & Safety

Enable Strict Mode

Always enable strict mode at the top of scripts:

#!/bin/bash
set -euo pipefail
  • -e: Exit on first error
  • -u: Treat unset variables as errors
  • -o pipefail: Surface pipeline failures

Cleanup with Traps

cleanup() {
    # Remove temporary files
    if [[ -n "${TEMP_DIR:-}" && -d "$TEMP_DIR" ]]; then
        rm -rf "$TEMP_DIR"
    fi

    # Close connections
    if [[ -n "${CONNECTION:-}" ]]; then
        echo "Closing connection..."
        # connection close logic
    fi
}

trap cleanup EXIT


trap 'echo "Interrupted"; cleanup; exit 1' INT TERM

Validate Requirements

validate_requirements() {
    local errors=0

    # Check required variables
    if [[ -z "${RESOURCE_GROUP:-}" ]]; then
        echo "Error: RESOURCE_GROUP environment variable not set" >&2
        ((errors++))
    fi

    # Check required commands
    for cmd in curl jq az; do
        if ! command -v "$cmd" &> /dev/null; then
            echo "Error: $cmd is not installed" >&2
            ((errors++))
        fi
    done

    # Return appropriate exit code
    return $errors
}


if ! validate_requirements; then
    exit 1
fi

Working with Variables



echo "Config: ${CONFIG_FILE:-./config.default.yaml}"


name="World"
echo "Hello, ${name}!"


apps=("app1" "app2" "app3")
for app in "${apps[@]}"; do
    echo "Processing: $app"
done


declare -A config
config[host]="localhost"
config[port]="8080"
echo "Connecting to ${config[host]}:${config[port]}"

Control Flow



if [[ "$OSTYPE" == "linux-gnu"* ]]; then
    echo "Linux detected"
elif [[ "$OSTYPE" == "darwin"* ]]; then
    echo "macOS detected"
else
    echo "Unknown OS"
fi


case "$1" in
    start)
        echo "Starting service..."
        ;;
    stop)
        echo "Stopping service..."
        ;;
    *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac


for i in {1..5}; do
    echo "Iteration $i"
done


timeout=30
elapsed=0
while [[ $elapsed -lt $timeout ]]; do
    if check_ready; then
        echo "Service ready"
        break
    fi
    sleep 1
    ((elapsed++))
done

Parsing JSON with jq



result=$(curl -s "https://api.example.com/data")
name=$(echo "$result" | jq -r '.name')
count=$(echo "$result" | jq '.items | length')
first_item=$(echo "$result" | jq -r '.items[0]')


active_users=$(echo "$result" | jq '.users[] | select(.status == "active")')


read -r first_name last_name email <<<$(echo "$result" | jq -r '"\(.firstName) \(.lastName) \(.email)"')


echo "$result" | jq '.count += 1' > updated.json


jq -n \
  --arg name "John" \
  --arg age "30" \
  '{name: $name, age: ($age | tonumber)}'

Parsing Arguments

#!/bin/bash


verbose=0
output_file="output.txt"
config="./config.yaml"


while [[ $# -gt 0 ]]; do
    case $1 in
        -v|--verbose)
            verbose=1
            shift
            ;;
        -o|--output)
            output_file="$2"
            shift 2
            ;;
        -c|--config)
            config="$2"
            shift 2
            ;;
        -h|--help)
            show_help
            exit 0
            ;;
        *)
            echo "Unknown option: $1" >&2
            exit 1
            ;;
    esac
done

echo "Config: $config"
echo "Output: $output_file"
echo "Verbose: $verbose"

File Operations



if [[ -f "$FILE_PATH" ]]; then
    echo "File exists"
fi


if [[ ! -d "$DIR_PATH" ]]; then
    mkdir -p "$DIR_PATH"
fi


mkdir -p ./dir1/dir2


cp -r source_dir/ dest_dir/


rm -f file.txt          # Force delete file
rm -rf directory/       # Recursive delete directory


find . -name "*.py"           # All Python files
find . -type f -name "*.js"   # All JS files (regular files only)
find . -mtime -7              # Modified in last 7 days


temp_file=$(mktemp)
echo "data" > "$temp_file"


rm -f "$temp_file"


temp_dir=$(mktemp -d)


rm -rf "$temp_dir"

Process Management



if pgrep -x "nginx" > /dev/null; then
    echo "Nginx is running"
else
    echo "Nginx is not running"
fi


while pgrep -x "script-name" > /dev/null; do
    sleep 1
done


timeout 30s ./long-running-script.sh || echo "Timed out after 30s"


./script.sh &
job_pid=$!


trap "kill $job_pid 2>/dev/null" EXIT

Logging

#!/bin/bash


LOG_INFO() {
    echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $*"
}

LOG_WARN() {
    echo "[WARN] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
}

LOG_ERROR() {
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
}

LOG_DEBUG() {
    if [[ "${DEBUG:-}" == "1" ]]; then
        echo "[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $*"
    fi
}


LOG_INFO "Starting deployment"
LOG_WARN "This is a warning"
LOG_ERROR "Deployment failed"
LOG_DEBUG "Detailed debugging info"

Part 3: PowerShell Scripting

General Practices

  • Use proper cmdlet names instead of aliases (e.g., Get-ChildItem, not dir)
  • Quote paths with spaces: "C:\Path With Spaces\file.txt"
  • Use ShouldProcess for destructive operations
  • Implement proper error handling with try-catch
  • Parameterize scripts for reusability

Error Handling



Set-StrictMode -Version Latest


$ErrorActionPreference = "Stop"


try {
    $result = Invoke-RestMethod -Uri "https://api.example.com/data" -Method Get
}
catch [System.Net.WebException] {
    Write-Error "Network error occurred: $($_.Exception.Message)"
    exit 1
}
catch {
    Write-Error "Unexpected error: $($_.Exception.Message)"
    exit 1
}
finally {
    # Cleanup code always runs
    Write-Output "Execution completed"
}


trap {
    Write-Error "Script failed: $_"
    # Cleanup code
    Remove-Variable -Name tempVar -ErrorAction SilentlyContinue
    exit 1
}

Parameter Handling

param(
    [Parameter(Mandatory=$true)]
    [string]$Name,

    [Parameter(Mandatory=$false)]
    [string]$Path = ".",

    [Parameter(Mandatory=$false)]
    [switch]$Verbose,

    [ValidateSet("dev", "staging", "prod")]
    [string]$Environment = "dev"
)

Write-Output "Name: $Name"
Write-Output "Path: $Path"
Write-Output "Environment: $Environment"
Write-Output "Verbose: $Verbose"

Working with Objects



$user = [PSCustomObject]@{
    Name = "John"
    Age = 30
    Email = "john@example.com",
    Address = "123 Main St"
}


Write-Output $user.Name


$user | Add-Member -MemberType NoteProperty -Name "City" -Value "Anytown"


$users | Where-Object { $_.Age -gt 25 }


$users | Select-Object Name, Email


$users | Sort-Object Name


$users | Group-Object City

Working with JSON



$json = '{"name": "John", "age": 30}'
$obj = $json | ConvertFrom-Json

Write-Output $obj.name


$data = @{ name = "John"; age = 30 }
$json = $data | ConvertTo-Json -Depth 10
Write-Output $json


$config = Get-Content "config.json" | ConvertFrom-Json


$config | ConvertTo-Json -Depth 10 | Set-Content "config.json"

Working with Arrays and Hashtables



$files = @("file1.txt", "file2.txt", "file3.txt")


$files += "file4.txt"


$filtered = $files | Where-Object { $_ -like "*.txt" }


$config = @{
    host = "localhost"
    port = 8080
    tls = $true
}


Write-Output $config.host


$key = "port"
Write-Output $config[$key]


foreach ($item in $config.GetEnumerator()) {
    Write-Output "$($item.Name) = $($item.Value)"
}

File Operations



if (Test-Path "C:\path\to\file.txt") {
    Write-Output "File exists"
}


New-Item -ItemType Directory -Path "C:\new\dir" -Force


Remove-Item "C:\path\to\file.txt" -Force
Remove-Item "C:\path\to\directory" -Recurse -Force


Copy-Item "source.txt" "destination.txt" -Force
Copy-Item "dir\" "backup\" -Recurse


Move-Item "old_name.txt" "new_name.txt"


$content = Get-Content "file.txt"
$content = Get-Content "file.txt" -Raw  # As single string


$content | Set-Content "file.txt"


"more content" | Add-Content "file.txt"

String Operations



$name = "John"
Write-Output "Hello, $name!"


Write-Output ("Hello, {0}! Your score is {1:N2}" -f $name, 95.5)


$string = "  Hello World  "


$trimmed = $string.Trim()


$replaced = $string.Replace("World", "PowerShell")


if ($string -like "*World*") {
    Write-Output "Contains 'World'"
}


if ($string -match "^Hello") {
    Write-Output "Starts with 'Hello'"
}


$parts = "a,b,c".Split(",")

Part 4: CI/CD Configuration

GitHub Actions

name: CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
  workflow_dispatch: # Allow manual trigger

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16.x, 18.x, 20.x]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Upload coverage
        uses: codecov/codecov-action@v3

  build:
    needs: test
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build
          path: dist/

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build

      - name: Deploy to Azure
        run: az webapp up --name myapp --resource-group myrg

Azure Pipelines

trigger:
- main
- develop

pool:
  vmImage: 'ubuntu-latest'

variables:
  buildConfiguration: 'Release'
  packageFolder: '$(build.artifactStagingDirectory)/package'

stages:
- stage: Build
  displayName: 'Build stage'
  jobs:
  - job: Build
    displayName: 'Build job'
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '18.x'
      displayName: 'Install Node.js'

    - script: |
        npm ci
      displayName: 'Install dependencies'

    - script: |
        npm run build
      displayName: 'Build application'

    - task: ArchiveFiles@2
      inputs:
        rootFolderOrFile: 'dist'
        includeRootFolder: false
        archiveType: 'zip'
        archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
      displayName: 'Archive build artifacts'

    - publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
      artifact: drop

- stage: Deploy
  displayName: 'Deploy stage'
  dependsOn: Build
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: Deploy
    displayName: 'Deploy job'
    environment: 'production'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebApp@1
            inputs:
              azureSubscription: 'your_subscription_id'
              appName: 'your_webapp_name'
              package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip

DevOps Best Practices

Git

  • Use conventional commits
  • Keep commits small and focused
  • Write clear, descriptive messages
  • Keep feature branches short-lived
  • Rebase feature branches before merging
  • Sign commits for security-critical projects

Shell Scripting

  • Always use strict mode (set -euo pipefail)
  • Quote variables properly
  • Handle errors gracefully with traps
  • Validate inputs and parameters
  • Use functions for reusability
  • Add proper error messages to stderr

PowerShell

  • Use strict mode for security
  • Use proper cmdlet names (no aliases)
  • Implement error handling with try-catch
  • Test scripts thoroughly
  • Use parameter validation
  • Handle pipeline errors properly

CI/CD

  • Use secure variable management for secrets
  • Cache dependencies to speed up builds
  • Run tests on multiple environments
  • Use matrix builds for different configurations
  • Implement proper artifact management
  • Add deployment gates and approvals
  • Provide clear build status

<!-- MCP:START --> <!-- PORTABILITY:START -->

Cross-Client Portability

This skill is written to stay usable across GitHub Copilot, Claude Code, and Codex.

  • GitHub Copilot: keep the folder in a Copilot-visible skill path or wrap the workflow in project instructions when folder discovery is unavailable.
  • Claude Code: keep the folder in a local skills directory or a compatible plugin source.
  • Codex: install or sync the folder into $CODEX_HOME/skills/devops-tooling and restart Codex after major changes.
<!-- PORTABILITY:END -->

MCP Availability And Fallback

Preferred MCP Server: GitHub MCP

  • Fallback prompt: "Use the Devops Tooling skill without MCP. Follow the documented local or manual fallback, show the selected tool surface, and report the verification evidence."
  • Use standard local tools such as git, gh, CI logs, and shell automation scripts for repository and pipeline work.
  • Prefer the bundled repo scripts or direct YAML edits when the MCP host does not expose GitHub operations.
  • Do not claim an MCP operation was used when the active host does not expose it.
<!-- MCP:END -->

Anti-Patterns

  • Starting work before the plan or gate is clear: Execution drifts when success criteria are implied instead of explicit.
  • Treating verification as optional cleanup: The last mile is where regressions and missing updates are usually hiding.
  • Mixing planning, implementation, and release work in one jump: You lose the causal chain that explains why a change is safe.

Verification Protocol

Before claiming "skill applied successfully":

  1. Pass/fail: The Devops Tooling workflow starts from explicit success criteria, constraints, and stop conditions.
  2. Pass/fail: Required evidence is collected before any completion, approval, or readiness claim.
  3. Pass/fail: The next action follows the documented gate order without skipping review or verification steps.
  4. Pressure-test scenario: Apply the workflow under time pressure with one failing check and one tempting shortcut.
  5. Success metric: Zero rationalizations; blocked, failed, or unverified work is reported as such.

References & Resources

Documentation

Scripts

  • Setup Git Hooks — PowerShell script to install pre-commit, commit-msg, and pre-push hooks

Examples


Related Skills

  • development-workflow: Use it when the workflow also needs planning, quality gates, and delivery tracking.
  • code-quality: Use it when the workflow also needs two-stage review (spec compliance first, then code quality), maintainability, and refactoring guidance.
  • systematic-debugging: Use it when the workflow also needs root-cause debugging before proposing fixes.
  • test-driven-development: Use it when the workflow also needs test-first implementation and regression safety.
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

devops-tooling

默认分支

main

最新提交

ff6d12f

Tree SHA

e96fd60