|
| 1 | +# Azure Pipelines Tasks - Copilot Instructions |
| 2 | + |
| 3 | +This repository contains the in-the-box tasks for Azure Pipelines and Team Foundation Server. These instructions will help you understand how to build, test, and deploy tasks effectively. |
| 4 | + |
| 5 | +## Repository Overview |
| 6 | + |
| 7 | +This repo provides open examples of how Azure Pipelines tasks are written and can help you write custom tasks for upload to your account or server. Tasks are tool runners that know how to execute tools like MSBuild, VSTest, etc., handle return codes, process stdout/stderr, write timeline records, and access credentials for Azure Pipelines integration. |
| 8 | + |
| 9 | +## Prerequisites |
| 10 | + |
| 11 | +### Required Tools |
| 12 | +- **Node.js**: Version 20 or higher is required (minimum 20.17.0) |
| 13 | +- **NPM**: Version 5.6.0 or higher |
| 14 | +- **TypeScript**: 4.0.2 or higher (automatically validated during build) |
| 15 | +- **.NET SDK**: 8.0.100 (automatically downloaded during build if needed) |
| 16 | + |
| 17 | +### Verification Commands |
| 18 | +```bash |
| 19 | +node -v && npm -v # Should show Node 20+ and NPM 5.6+ |
| 20 | +``` |
| 21 | + |
| 22 | +### Initial Setup |
| 23 | +```bash |
| 24 | +# Install repository dependencies (required before building any tasks) |
| 25 | +npm install |
| 26 | +``` |
| 27 | + |
| 28 | +## Building Tasks |
| 29 | + |
| 30 | +### Build System Overview |
| 31 | +The repository uses a custom build system (`make.js`) that: |
| 32 | +- Compiles TypeScript to JavaScript |
| 33 | +- Handles task dependencies and external tools |
| 34 | +- Generates localization files (`task.loc.json` and strings) |
| 35 | +- Validates task definitions |
| 36 | +- Copies resources to the `_build` directory |
| 37 | + |
| 38 | +### Build Commands |
| 39 | + |
| 40 | +#### Build a Specific Task (Recommended) |
| 41 | +```bash |
| 42 | +# From repository root |
| 43 | +node make.js build --task <TaskName> |
| 44 | + |
| 45 | +# Example: Build DotNetCoreCLIV2 task |
| 46 | +node make.js build --task DotNetCoreCLIV2 |
| 47 | + |
| 48 | +# From task directory |
| 49 | +cd Tasks/<TaskName> |
| 50 | +npm run build |
| 51 | +``` |
| 52 | + |
| 53 | +#### Build All Tasks (Slow - Can Take 30+ Minutes) |
| 54 | +```bash |
| 55 | +npm run build |
| 56 | +# OR |
| 57 | +node make.js build |
| 58 | +``` |
| 59 | + |
| 60 | +#### Server Build (For CI Environments) |
| 61 | +```bash |
| 62 | +node make.js serverBuild --task <TaskName> |
| 63 | +``` |
| 64 | + |
| 65 | +#### Build with Bypassed NPM Audit |
| 66 | +```bash |
| 67 | +node make.js build --task <TaskName> --BypassNpmAudit |
| 68 | +``` |
| 69 | + |
| 70 | +#### Debug Build (For Agent Debugging) |
| 71 | +```bash |
| 72 | +node make.js build --task <TaskName> --debug-agent-dir "<path-to-agent-directory>" |
| 73 | +``` |
| 74 | + |
| 75 | +### Build Output |
| 76 | +Built tasks are located in: `_build/Tasks/<TaskName>/` |
| 77 | + |
| 78 | +The build process creates: |
| 79 | +- Compiled JavaScript files from TypeScript source |
| 80 | +- `task.json` and `task.loc.json` (localization metadata) |
| 81 | +- Resource files (PowerShell scripts, icons, etc.) |
| 82 | +- Node modules and dependencies |
| 83 | +- External tools and dependencies |
| 84 | + |
| 85 | +## Testing Tasks |
| 86 | + |
| 87 | +### Test Types |
| 88 | + |
| 89 | +#### Unit Tests (L0) |
| 90 | +Fast tests that mock external dependencies: |
| 91 | +```bash |
| 92 | +# Test specific task |
| 93 | +node make.js test --task <TaskName> --suite L0 |
| 94 | + |
| 95 | +# Test all built tasks |
| 96 | +npm test |
| 97 | +# OR |
| 98 | +node make.js test |
| 99 | +``` |
| 100 | + |
| 101 | +#### Integration Tests (L1) |
| 102 | +Tests that use real external tools but avoid network calls: |
| 103 | +```bash |
| 104 | +node make.js test --task <TaskName> --suite L1 |
| 105 | +``` |
| 106 | + |
| 107 | +#### End-to-End Tests (L2) |
| 108 | +Full integration tests with real services: |
| 109 | +```bash |
| 110 | +node make.js test --task <TaskName> --suite L2 |
| 111 | +``` |
| 112 | + |
| 113 | +#### Legacy Tests |
| 114 | +```bash |
| 115 | +# All legacy tests |
| 116 | +node make.js testLegacy |
| 117 | + |
| 118 | +# Specific task legacy tests |
| 119 | +node make.js testLegacy --task <TaskName> |
| 120 | +``` |
| 121 | + |
| 122 | +### Test Debugging |
| 123 | +Set environment variable for additional logging: |
| 124 | +```bash |
| 125 | +export TASK_TEST_TRACE=1 |
| 126 | +node make.js test --task <TaskName> |
| 127 | +``` |
| 128 | + |
| 129 | +## End-to-End Testing and Deployment |
| 130 | + |
| 131 | +### Prepare Task for E2E Testing |
| 132 | + |
| 133 | +1. **Modify Task GUID** (Critical - Prevents Conflicts) |
| 134 | + ```bash |
| 135 | + # Edit both task.json and task.loc.json |
| 136 | + # Change the "id" field to a unique test GUID |
| 137 | + # Use online GUID generator or: uuidgen (macOS/Linux) |
| 138 | + ``` |
| 139 | + |
| 140 | +2. **Optional: Modify Task Name** |
| 141 | + ```bash |
| 142 | + # Edit task.json - change "name" field for easy YAML referencing |
| 143 | + # Example: "DotNetCoreCLI" -> "DotNetCoreCLITest" |
| 144 | + ``` |
| 145 | + |
| 146 | +3. **Build the Task** |
| 147 | + ```bash |
| 148 | + node make.js build --task <TaskName> |
| 149 | + ``` |
| 150 | + |
| 151 | +### Deploy Task to Azure DevOps |
| 152 | + |
| 153 | +#### Install TFX CLI |
| 154 | +```bash |
| 155 | +# Linux/macOS |
| 156 | +sudo npm install -g tfx-cli |
| 157 | + |
| 158 | +# Windows |
| 159 | +npm install -g tfx-cli |
| 160 | +``` |
| 161 | + |
| 162 | +#### Create Personal Access Token |
| 163 | +1. Navigate to Azure DevOps → User Settings → Personal Access Tokens |
| 164 | +2. Click "+ New Token" |
| 165 | +3. Name your token |
| 166 | +4. Choose "Custom Defined" → Select "Environment (Read & Write)" OR "Full Access" |
| 167 | +5. Copy and save the token securely |
| 168 | + |
| 169 | +#### Upload Task |
| 170 | + |
| 171 | +**Method 1: Interactive Login** |
| 172 | +```bash |
| 173 | +# Login to Azure DevOps |
| 174 | +tfx login |
| 175 | +# Enter Service URL: https://<YOUR_ORGANISATION>.visualstudio.com/defaultcollection |
| 176 | +# Enter your Personal Access Token |
| 177 | + |
| 178 | +# Upload task |
| 179 | +tfx build tasks upload --task-path _build/Tasks/<TaskName> |
| 180 | +``` |
| 181 | + |
| 182 | +**Method 2: One Command Upload** |
| 183 | +```bash |
| 184 | +tfx build tasks upload \ |
| 185 | + -u https://<YOUR_ORGANISATION>.visualstudio.com/DefaultCollection \ |
| 186 | + -t <YOUR_PERSONAL_ACCESS_TOKEN> \ |
| 187 | + --task-path _build/Tasks/<TaskName> |
| 188 | +``` |
| 189 | + |
| 190 | +#### Important Notes for Local Azure DevOps Server |
| 191 | +- Default collections may require old domain format |
| 192 | +- Use: `https://<YOUR_ORGANISATION>.vsts.me/DefaultCollection` |
| 193 | +- Even if your org is on newer domains like `codedev.ms` |
| 194 | + |
| 195 | +### Testing in Azure Pipelines |
| 196 | + |
| 197 | +After uploading, create a test pipeline: |
| 198 | +```yaml |
| 199 | +trigger: none |
| 200 | + |
| 201 | +pool: |
| 202 | + vmImage: 'ubuntu-latest' |
| 203 | + |
| 204 | +steps: |
| 205 | +- task: YourTestTaskName@1 |
| 206 | + inputs: |
| 207 | + # Your task inputs here |
| 208 | +``` |
| 209 | + |
| 210 | +## Available CLI Commands |
| 211 | + |
| 212 | +```bash |
| 213 | +node make.js <command> [options] |
| 214 | + |
| 215 | +Commands: |
| 216 | + build # Build tasks for development |
| 217 | + serverBuild # Build with full validation (CI) |
| 218 | + buildandtest # Build and run tests |
| 219 | + test # Run tests for built tasks |
| 220 | + testLegacy # Run legacy tests |
| 221 | + clean # Clean build directories |
| 222 | + package # Package tasks for distribution |
| 223 | + bump # Bump task versions |
| 224 | + gendocs # Generate documentation |
| 225 | +``` |
| 226 | + |
| 227 | +## Task Structure |
| 228 | + |
| 229 | +### Key Files |
| 230 | +- `task.json` - Task definition and metadata |
| 231 | +- `task.loc.json` - Localization template (auto-generated) |
| 232 | +- `package.json` - Node dependencies and build scripts |
| 233 | +- `tsconfig.json` - TypeScript configuration |
| 234 | +- `*.ts` - TypeScript source files |
| 235 | +- `Tests/` - Test files and test data |
| 236 | +- `Strings/` - Localization files |
| 237 | + |
| 238 | +### Common Dependencies |
| 239 | +- `azure-pipelines-task-lib` - Core task library |
| 240 | +- `azure-pipelines-tool-lib` - Tool installation library |
| 241 | +- Various task-specific common packages |
| 242 | + |
| 243 | +## Development Workflow |
| 244 | + |
| 245 | +1. **Setup Environment** |
| 246 | + ```bash |
| 247 | + npm install |
| 248 | + ``` |
| 249 | + |
| 250 | +2. **Make Changes** |
| 251 | + - Edit TypeScript source files |
| 252 | + - Update task.json if needed |
| 253 | + - Add/update tests |
| 254 | + |
| 255 | +3. **Build and Test** |
| 256 | + ```bash |
| 257 | + node make.js build --task <TaskName> |
| 258 | + node make.js test --task <TaskName> --suite L0 |
| 259 | + ``` |
| 260 | + |
| 261 | +4. **E2E Testing** |
| 262 | + - Modify GUID in task.json and task.loc.json |
| 263 | + - Build and upload to test Azure DevOps org |
| 264 | + - Create test pipeline and validate functionality |
| 265 | + |
| 266 | +5. **Submit Changes** |
| 267 | + - Ensure all tests pass |
| 268 | + - Check in generated files (task.loc.json, strings) |
| 269 | + - Submit pull request |
| 270 | + |
| 271 | +## Troubleshooting |
| 272 | + |
| 273 | +### Common Build Issues |
| 274 | +- **Missing dependencies**: Run `npm install` in repository root |
| 275 | +- **Node version**: Ensure Node.js 20+ is installed |
| 276 | +- **TypeScript errors**: Check tsconfig.json and update code |
| 277 | +- **External tool failures**: Check network connectivity |
| 278 | + |
| 279 | +### Common Test Issues |
| 280 | +- **Mock failures**: Verify mock data in Tests/ directory |
| 281 | +- **Environment variables**: Set TASK_TEST_TRACE=1 for debugging |
| 282 | +- **Tool dependencies**: Ensure required tools are available |
| 283 | + |
| 284 | +### Upload Issues |
| 285 | +- **Authentication**: Verify PAT has correct permissions |
| 286 | +- **URL format**: Use correct collection URL format |
| 287 | +- **GUID conflicts**: Ensure unique GUID for test tasks |
| 288 | + |
| 289 | +## Best Practices |
| 290 | + |
| 291 | +1. **Always test locally** before uploading to Azure DevOps |
| 292 | +2. **Use unique GUIDs** for test tasks to avoid conflicts |
| 293 | +3. **Include comprehensive unit tests** (L0 suite) |
| 294 | +4. **Follow existing task patterns** in the repository |
| 295 | +5. **Update localization files** when changing task.json |
| 296 | +6. **Test cross-platform** if task supports multiple OS |
| 297 | +7. **Document task inputs/outputs** in task.json descriptions |
| 298 | + |
| 299 | +## Resources |
| 300 | + |
| 301 | +- [Azure Pipelines Task Documentation](https://docs.microsoft.com/azure/devops/pipelines/tasks/) |
| 302 | +- [Writing Custom Tasks](https://docs.microsoft.com/azure/devops/extend/develop/add-build-task) |
| 303 | +- [TFS CLI Documentation](https://github.com/Microsoft/tfs-cli) |
| 304 | +- [Task Library API](https://github.com/Microsoft/azure-pipelines-task-lib) |
0 commit comments