Skip to content

Commit

Permalink
Add experimental 'local-deploy' command group to Bicep CLI (#14243)
Browse files Browse the repository at this point in the history
This change brings in the following:
* New `local-deploy` command group to deploy a Bicep file using the
local extensibility preview.
* Additions to `publish-provider` command group to allow publishing a
binary extension to an ACR or to file system.

To test it out (see "Test this change out" comment below first):
* `bicepconfig.json`:
    ```json
    {
      "experimentalFeaturesEnabled": {
        "extensibility": true,
        "localDeploy": true,
        "providerRegistry": true
      }
    }
    ```
* `main.bicep`:
    ```bicep
    provider 'br:biceplocaldeploy.azurecr.io/providers/http:0.1.9'
    
    param coords {
      lattitude: string
      longitude: string
    }
    
    resource gridpointsReq 'HttpRequest' = {
uri:
'https://api.weather.gov/points/${coords.lattitude},${coords.longitude}'
      format: 'raw'
    }
    
    var gridpoints = json(gridpointsReq.body).properties
    
    resource forecastReq 'HttpRequest' = {
uri:
'https://api.weather.gov/gridpoints/${gridpoints.gridId}/${gridpoints.gridX},${gridpoints.gridY}/forecast'
      format: 'raw'
    }
    
    var forecast = json(forecastReq.body).properties
    
    type forecastType = {
      name: string
      temperature: int
    }
    
    output forecast forecastType[] = map(forecast.periods, p => {
      name: p.name
      temperature: p.temperature
    })
    ```
* `main.bicepparam`:
    ```bicep
    using 'main.bicep'
    
    param coords = {
      lattitude: '47.6363726'
      longitude: '-122.1357068'
    }
    ```
* CLI command:
    ```sh
    ~/.azure/bin/bicep local-deploy ~/path/to/main.bicepparam
    ```

###### Microsoft Reviewers: [Open in
CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/Azure/bicep/pull/14243)
  • Loading branch information
anthony-c-martin authored Jun 7, 2024
1 parent 664d4db commit 91b64d4
Show file tree
Hide file tree
Showing 85 changed files with 33,495 additions and 1,216 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ jobs:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
submodules: true

- name: Setup .NET Core
uses: actions/setup-dotnet@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
Expand Down Expand Up @@ -549,6 +552,7 @@ jobs:
entrypoint: sh
args: -c "apk add --update nodejs npm && npm ci --prefix ./src/Bicep.Cli.E2eTests && npm test --prefix ./src/Bicep.Cli.E2eTests"
env:
BICEP_CLI_DOTNET_RID: ${{ matrix.runtime.rid }}
BICEP_CLI_EXECUTABLE: ../../../Bicep.Cli.E2eTests/src/temp/bicep-cli/bicep

test-dotnet:
Expand Down Expand Up @@ -711,6 +715,9 @@ jobs:
with:
node-version: 18

- name: Setup .NET Core
uses: actions/setup-dotnet@v4

- name: Download Bicep CLI
uses: actions/download-artifact@v4
with:
Expand Down Expand Up @@ -778,6 +785,7 @@ jobs:
- name: Run Bicep Live E2E Tests (${{ matrix.environment }})
run: npm ci && npm run test:live:${{ matrix.environment }}
env:
BICEP_CLI_DOTNET_RID: ${{ matrix.runtime.rid }}
BICEP_CLI_EXECUTABLE: ../../../Bicep.Cli.E2eTests/src/temp/bicep-cli/bicep
working-directory: ./src/Bicep.Cli.E2eTests

Expand Down
7 changes: 7 additions & 0 deletions Bicep.sln
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bicep.Local.Deploy", "src\B
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bicep.Local.Deploy.IntegrationTests", "src\Bicep.Local.Deploy.IntegrationTests\Bicep.Local.Deploy.IntegrationTests.csproj", "{3F25D072-7A7E-419D-8425-6F2C7CF42BFD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bicep.Local.Extension.Mock", "src\Bicep.Local.Extension.Mock\Bicep.Local.Extension.Mock.csproj", "{A7D359D9-654A-4FAF-9BC2-DA9667EF8756}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -189,6 +191,10 @@ Global
{3F25D072-7A7E-419D-8425-6F2C7CF42BFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F25D072-7A7E-419D-8425-6F2C7CF42BFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F25D072-7A7E-419D-8425-6F2C7CF42BFD}.Release|Any CPU.Build.0 = Release|Any CPU
{A7D359D9-654A-4FAF-9BC2-DA9667EF8756}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7D359D9-654A-4FAF-9BC2-DA9667EF8756}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7D359D9-654A-4FAF-9BC2-DA9667EF8756}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7D359D9-654A-4FAF-9BC2-DA9667EF8756}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -217,6 +223,7 @@ Global
{E84C0368-0D02-4284-A3CB-110B14FA8314} = {8F8DCFBC-A0DC-4E40-93C8-B4FB99FBD757}
{3F3A6387-DD5F-40A6-89D1-92653E4872D3} = {8F8DCFBC-A0DC-4E40-93C8-B4FB99FBD757}
{3F25D072-7A7E-419D-8425-6F2C7CF42BFD} = {8F8DCFBC-A0DC-4E40-93C8-B4FB99FBD757}
{A7D359D9-654A-4FAF-9BC2-DA9667EF8756} = {8F8DCFBC-A0DC-4E40-93C8-B4FB99FBD757}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {21F77282-91E7-4304-B1EF-FADFA4F39E37}
Expand Down
4 changes: 2 additions & 2 deletions src/Bicep.Cli.E2eTests/src/examples/101/aks.prod/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.23.35.39852",
"templateHash": "6457398673135247172"
"version": "0.28.8.24706",
"templateHash": "13279681427225276221"
}
},
"parameters": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"experimentalFeaturesEnabled": {
"extensibility": true,
"providerRegistry": true,
"localDeploy": true
}
}
9 changes: 9 additions & 0 deletions src/Bicep.Cli.E2eTests/src/examples/local-deploy/main.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
provider '../../temp/local-deploy/provider.tgz'

param payload string

resource sayHi 'echo' = {
payload: payload
}

output sayHiResult string = sayHi.payload
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using 'main.bicep'

param payload = 'Hello, World!'
91 changes: 91 additions & 0 deletions src/Bicep.Cli.E2eTests/src/localDeploy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/**
* Tests for "bicep local-deploy".
*
* @group CI
*/

import spawn from "cross-spawn";
import os from "os";
import path from "path";
import { invokingBicepCommand } from "./utils/command";
import {
ensureParentDirExists,
expectFileExists,
pathToExampleFile,
pathToTempFile,
} from "./utils/fs";

const itif = (condition: boolean) => condition ? it : it.skip;
const cliDotnetRid = process.env.BICEP_CLI_DOTNET_RID;
// We don't have an easy way of running this test for linux-musl-x64 RID, so skip for now.
const canRunLocalDeploy = () => !cliDotnetRid || architectures.map(x => x.dotnetRid).includes(cliDotnetRid);

const mockExtensionExeName = 'bicep-ext-mock';
const mockExtensionProjPath = path.resolve(
__dirname,
"../../Bicep.Local.Extension.Mock"
);

const architectures = [
{ dotnetRid: 'osx-arm64', bicepArgs: ['--bin-osx-arm64', `${mockExtensionProjPath}/bin/release/net8.0/osx-arm64/publish/${mockExtensionExeName}`] },
{ dotnetRid: 'osx-x64', bicepArgs: ['--bin-osx-x64', `${mockExtensionProjPath}/bin/release/net8.0/osx-x64/publish/${mockExtensionExeName}`] },
{ dotnetRid: 'linux-x64', bicepArgs: ['--bin-linux-x64', `${mockExtensionProjPath}/bin/release/net8.0/linux-x64/publish/${mockExtensionExeName}`] },
{ dotnetRid: 'win-x64', bicepArgs: ['--bin-win-x64', `${mockExtensionProjPath}/bin/release/net8.0/win-x64/publish/${mockExtensionExeName}.exe`] },
];

describe("bicep local-deploy", () => {
itif(canRunLocalDeploy())("should build and deploy a provider published to the local file system", () => {

for (const arch of architectures) {
execDotnet(['publish', '--verbosity', 'quiet', '--configuration', 'release', '--self-contained', 'true', '-r', arch.dotnetRid, mockExtensionProjPath]);
}

const typesIndexPath = pathToTempFile("local-deploy", "types", "index.json");
const typesDir = path.dirname(typesIndexPath);
ensureParentDirExists(typesIndexPath);

execDotnet(['run', '--verbosity', 'quiet', '--project', mockExtensionProjPath], {
MOCK_TYPES_OUTPUT_PATH: typesDir,
});

const targetPath = pathToTempFile("local-deploy", "provider.tgz");

invokingBicepCommand(
"publish-provider",
typesIndexPath,
"--target",
targetPath,
...(architectures.flatMap(arch => arch.bicepArgs))
)
.shouldSucceed()
.withEmptyStdout();

expectFileExists(targetPath);

const bicepparamFilePath = pathToExampleFile("local-deploy", "main.bicepparam");

invokingBicepCommand("local-deploy", bicepparamFilePath)
.shouldSucceed()
.withStdout([
'Output sayHiResult: "Hello, World!"',
'Resource sayHi (Create): Succeeded',
'Result: Succeeded',
''
].join(os.EOL));
});
});

function execDotnet(args: string[], envOverrides?: NodeJS.ProcessEnv) {
const result = spawn.sync('dotnet', args, {
encoding: 'utf-8',
stdio: 'inherit',
env: {
...process.env,
...(envOverrides ?? {})
}
});
expect(result.status).toBe(0);
}
2 changes: 1 addition & 1 deletion src/Bicep.Cli.E2eTests/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"moduleResolution": "node",
"esModuleInterop": true,
"outDir": "out",
"lib": ["es2016"],
"lib": ["es2019"],
"sourceMap": true,
"skipLibCheck": true,
"strict": true,
Expand Down
5 changes: 3 additions & 2 deletions src/Bicep.Cli.IntegrationTests/BuildCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,9 @@ public async Task Build_Valid_SingleFile_WithProviderDeclarationStatement(
foreach (var ((uri, _), client) in blobClients)
{
if (uri.Host.Contains("invalid")) { continue; }
await client.SetManifestAsync(BicepTestConstants.BicepProviderManifestWithEmptyTypesLayer, "2.0.0");
await client.UploadBlobAsync(new MemoryStream());
var layer = await client.UploadBlobAsync(BinaryData.FromString(""));
var config = await client.UploadBlobAsync(BinaryData.FromString("{}"));
await client.SetManifestAsync(BicepTestConstants.GetBicepProviderManifest(layer, config), "2.0.0");
}

// 3. create a main.bicep and save it to a output directory
Expand Down
Loading

0 comments on commit 91b64d4

Please sign in to comment.