能否基于存储账户Blob更新触发VSTS/TFS构建?函数App尝试失败求助
Absolutely! You can absolutely trigger a VSTS/TFS build when a Blob in your Azure Storage account gets updated—let’s fix that Function App setup since your first attempt didn’t pan out. Here’s a reliable, step-by-step solution:
First, make sure your Function App is using the correct trigger type and has proper permissions:
- When creating your function, select the Blob trigger template (not HTTP or other triggers). Specify your storage account connection string, target container name, and a blob path pattern (e.g.,
my-container/{name}to target all blobs in that container). - Verify the connection string uses either a storage account access key or a managed identity assigned the Storage Blob Data Contributor role on the container—this ensures the function can detect blob changes.
- Note: Blob triggers use polling by default, so it might take 1-2 minutes to pick up new blobs initially. If you need near-real-time triggers, pair it with Azure Event Grid (more on that later).
Once the trigger fires, your function needs to send a request to the VSTS/TFS Build API to start the build. Here’s how to do it right:
- Create a Personal Access Token (PAT) in your VSTS/TFS instance with the Build (read & execute) scope. Store this PAT in your Function App’s Application Settings (never hardcode it—use
Environment.GetEnvironmentVariableorprocess.envto retrieve it). - Add the API call code to your function. Below are snippets for common languages:
C# Example
using System; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Host; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; public static async Task Run(Stream myBlob, string name, TraceWriter log) { log.Info($"Processed blob: {name} (Size: {myBlob.Length} Bytes)"); // Replace with your VSTS/TFS details var accountName = "your-vsts-account"; var projectName = "your-project"; var buildDefinitionId = 123; // Get this from your build definition's URL var pat = Environment.GetEnvironmentVariable("VSTS_PAT"); using (var client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // Encode PAT for basic auth client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($":{pat}"))); var apiUrl = $"https://{accountName}.visualstudio.com/{projectName}/_apis/build/builds?api-version=6.0"; var buildPayload = new { definition = new { id = buildDefinitionId } }; var response = await client.PostAsJsonAsync(apiUrl, buildPayload); response.EnsureSuccessStatusCode(); // Throws an error if the API call fails log.Info($"Build triggered successfully! Response: {await response.Content.ReadAsStringAsync()}"); } }
JavaScript Example
const axios = require('axios'); module.exports = async function (context, myBlob) { context.log(`Processed blob: ${context.bindingData.name} (Size: ${myBlob.length} Bytes)`); // Replace with your VSTS/TFS details const accountName = "your-vsts-account"; const projectName = "your-project"; const buildDefinitionId = 123; const pat = process.env.VSTS_PAT; const auth = Buffer.from(`:${pat}`).toString('base64'); const apiUrl = `https://${accountName}.visualstudio.com/${projectName}/_apis/build/builds?api-version=6.0`; try { const response = await axios.post(apiUrl, { definition: { id: buildDefinitionId } }, { headers: { 'Authorization': `Basic ${auth}`, 'Content-Type': 'application/json' } }); context.log(`Build triggered! Response: ${JSON.stringify(response.data)}`); } catch (error) { context.log.error(`Failed to trigger build: ${error.message}`); throw error; } };
- For JavaScript, don’t forget to install
axiosby adding apackage.jsonwith"axios": "^1.6.0"and deploying it with your function.
If your first Function App didn’t work, check these common issues:
- Blob trigger not firing: Double-check the blob path pattern matches where you’re uploading blobs. Also, ensure your storage account isn’t a classic storage account (blob triggers work best with general-purpose v2 accounts).
- API call failing: Verify your PAT has the correct scope, and the API URL is right (for on-prem TFS, use
http://your-tfs-server:8080/tfs/CollectionName/ProjectName/_apis/build/builds?api-version=6.0). - Network blocks: If your VSTS/TFS is behind a firewall, add your Function App’s outbound IP addresses to the allowed list.
If you don’t want to write code, this is a great option:
- Create an Azure Logic App with an Event Grid trigger that listens for blob creation/modification events from your storage account.
- Add an Azure DevOps action to "Create a build", authenticate with your PAT, and select your project and build definition.
- This setup handles payload transformation automatically and is easier to debug without code.
Test by uploading or modifying a blob in your container—you should see the build start in VSTS/TFS within minutes (or seconds if using Event Grid).
内容的提问来源于stack exchange,提问作者Rafael

