1
1
import path = require( 'path' ) ;
2
2
import tl = require( 'azure-pipelines-task-lib/task' ) ;
3
3
import trm = require( 'azure-pipelines-task-lib/toolrunner' ) ;
4
+ import fs = require( 'fs' ) ;
5
+
6
+ const appLocationInputName = 'app_location' ;
7
+ const appBuildCommandInputName = 'app_build_command' ;
8
+ const outputLocationInputName = 'output_location' ;
9
+ const apiLocationInputName = 'api_location' ;
10
+ const apiBuildCommandInputName = 'api_build_command' ;
11
+ const routesLocationInputName = 'routes_location' ;
12
+ const buildTimeoutInMinutesInputName = 'build_timeout_in_minutes' ;
13
+ const configFileLocationInputName = 'config_file_location' ;
14
+ const apiTokenInputName = 'azure_static_web_apps_api_token' ;
4
15
5
16
async function run ( ) {
17
+ const envVarFilePath : string = path . join ( __dirname , 'env.list' ) ;
18
+
6
19
try {
7
20
tl . setResourcePath ( path . join ( __dirname , 'task.json' ) ) ;
8
21
@@ -19,39 +32,126 @@ async function run() {
19
32
20
33
bash . line ( tl . getInput ( 'args' , false ) ) ;
21
34
22
- const deploymentClient = "mcr.microsoft.com/appsvc/staticappsclient:stable" ;
23
-
24
- const workingDirectory : string = tl . getInput ( 'cwd' , false ) || "" ;
25
- const appLocation : string = tl . getInput ( 'app_location' , false ) || "" ;
26
- const appBuildCommand : string = tl . getInput ( 'app_build_command' , false ) || "" ;
27
- const outputLoction : string = tl . getInput ( 'output_location' , false ) || "" ;
28
- const apiLocation : string = tl . getInput ( 'api_location' , false ) || "" ;
29
- const apiBuildCommand : string = tl . getInput ( 'api_build_command' , false ) || "" ;
30
- const routesLocation : string = tl . getInput ( 'routes_location' , false ) || "" ;
31
- const skipAppBuild : boolean = tl . getBoolInput ( 'skip_app_build' , false ) ;
32
- const apiToken : string = process . env [ 'azure_static_web_apps_api_token' ] || tl . getInput ( 'azure_static_web_apps_api_token' , false ) || "" ;
33
-
34
- process . env [ 'SWA_WORKING_DIR' ] = workingDirectory ;
35
- process . env [ 'SWA_APP_LOCATION' ] = appLocation ;
36
- process . env [ 'SWA_APP_BUILD_COMMAND' ] = appBuildCommand ;
37
- process . env [ 'SWA_OUTPUT_LOCATION' ] = outputLoction ;
38
- process . env [ 'SWA_API_LOCATION' ] = apiLocation ;
39
- process . env [ 'SWA_API_BUILD_COMMAND' ] = apiBuildCommand ;
40
- process . env [ 'SWA_ROUTES_LOCATION' ] = routesLocation ;
41
- process . env [ 'SWA_DEPLOYMENT_CLIENT' ] = deploymentClient ;
42
- process . env [ 'SWA_SKIP_APP_BUILD' ] = skipAppBuild . toString ( ) ;
43
- process . env [ 'SWA_API_TOKEN' ] = apiToken ;
44
-
35
+ await createDockerEnvVarFile ( envVarFilePath ) ;
36
+
45
37
const options = {
46
38
failOnStdErr : false
47
39
} ;
48
40
49
41
await bash . exec ( < any > options ) ;
50
42
tl . setResult ( tl . TaskResult . Succeeded , null ) ;
43
+ } catch ( err ) {
44
+ tl . setResult ( tl . TaskResult . Failed , err ) ;
45
+ } finally {
46
+ await fs . promises . unlink ( envVarFilePath ) . catch ( ( ) => tl . warning ( "Unable to delete env file" ) ) ;
47
+ }
48
+ }
49
+
50
+ async function createDockerEnvVarFile ( envVarFilePath : string ) {
51
+ var variableString : string = ""
52
+
53
+ const systemVariableNames : Set < string > = new Set < string > ( ) ;
54
+
55
+ const addVariableToString = ( envVarName : string , envVarValue : string ) => variableString += envVarName + "=" + envVarValue + "\n"
56
+
57
+ const addSystemVariableToString = ( envVarName : string , envVarValue : string ) => {
58
+ addVariableToString ( envVarName , envVarValue )
59
+ systemVariableNames . add ( envVarName )
60
+ }
61
+
62
+ const addInputStringToString = ( envVarName : string , envVarValue : string , inputName : string , ) => {
63
+ if ( envVarValue . includes ( "\n" ) ) {
64
+ throw "Input " + inputName + " is a multiline string and cannot be added to the build environment." ;
65
+ }
66
+
67
+ addSystemVariableToString ( envVarName , envVarValue )
68
+ }
69
+
70
+ const workingDirectory : string = tl . getInput ( 'cwd' , false ) || process . env . SYSTEM_DEFAULTWORKINGDIRECTORY ;
71
+ const appLocation : string = tl . getInput ( appLocationInputName , false ) || "" ;
72
+ const appBuildCommand : string = tl . getInput ( appBuildCommandInputName , false ) || "" ;
73
+ const outputLocation : string = tl . getInput ( outputLocationInputName , false ) || "" ;
74
+ const apiLocation : string = tl . getInput ( apiLocationInputName , false ) || "" ;
75
+ const apiBuildCommand : string = tl . getInput ( apiBuildCommandInputName , false ) || "" ;
76
+ const routesLocation : string = tl . getInput ( routesLocationInputName , false ) || "" ;
77
+ const buildTimeoutInMinutes : string = tl . getInput ( buildTimeoutInMinutesInputName , false ) || "" ;
78
+ const configFileLocation : string = tl . getInput ( configFileLocationInputName , false ) || "" ;
79
+
80
+ const skipAppBuild : boolean = tl . getBoolInput ( 'skip_app_build' , false ) ;
81
+ const apiToken : string = process . env [ apiTokenInputName ] || tl . getInput ( apiTokenInputName , false ) || "" ;
82
+
83
+ const systemVerbose = getNullableBooleanFromString ( process . env [ 'SYSTEM_DEBUG' ] ) ;
84
+ const inputVerbose = getNullableBooleanFromString ( tl . getInput ( 'verbose' , false ) ) ;
85
+
86
+ const verbose = inputVerbose === true ? true : ( inputVerbose === false ? false : systemVerbose === true ) ;
87
+
88
+ const deploymentClient = "mcr.microsoft.com/appsvc/staticappsclient:stable" ;
89
+ const containerWorkingDir = "/working_dir" ;
90
+
91
+ addInputStringToString ( "APP_LOCATION" , appLocation , appLocationInputName ) ;
92
+ addInputStringToString ( "APP_BUILD_COMMAND" , appBuildCommand , appBuildCommandInputName ) ;
93
+ addInputStringToString ( "OUTPUT_LOCATION" , outputLocation , outputLocationInputName ) ;
94
+ addInputStringToString ( "API_LOCATION" , apiLocation , apiLocationInputName ) ;
95
+ addInputStringToString ( "API_BUILD_COMMAND" , apiBuildCommand , apiBuildCommandInputName ) ;
96
+ addInputStringToString ( "ROUTES_LOCATION" , routesLocation , routesLocationInputName ) ;
97
+ addInputStringToString ( "BUILD_TIMEOUT_IN_MINUTES" , buildTimeoutInMinutes , buildTimeoutInMinutesInputName ) ;
98
+ addInputStringToString ( "CONFIG_FILE_LOCATION" , configFileLocation , configFileLocationInputName ) ;
99
+
100
+ addSystemVariableToString ( "SKIP_APP_BUILD" , skipAppBuild . toString ( ) ) ;
101
+ addSystemVariableToString ( "VERBOSE" , verbose . toString ( ) ) ;
102
+
103
+ addInputStringToString ( "DEPLOYMENT_TOKEN" , apiToken , apiTokenInputName ) ;
104
+
105
+ process . env [ 'SWA_DEPLOYMENT_CLIENT' ] = deploymentClient ;
106
+ process . env [ 'SWA_WORKING_DIR' ] = workingDirectory ;
107
+ process . env [ 'SWA_WORKSPACE_DIR' ] = containerWorkingDir ;
108
+
109
+ addSystemVariableToString ( "GITHUB_WORKSPACE" , "" ) ;
110
+ addSystemVariableToString ( "DEPLOYMENT_PROVIDER" , "DevOps" ) ;
111
+ addSystemVariableToString ( "REPOSITORY_URL" , process . env . BUILD_REPOSITORY_URI || "" ) ;
112
+ addSystemVariableToString ( "IS_PULL_REQUEST" , "" ) ;
113
+ addSystemVariableToString ( "BASE_BRANCH" , "" ) ;
114
+ addSystemVariableToString ( "REPOSITORY_BASE" , containerWorkingDir ) ;
115
+ addSystemVariableToString ( "BRANCH" , process . env . BUILD_SOURCEBRANCHNAME || "" ) ;
116
+ addSystemVariableToString ( "DEPLOYMENT_ACTION" , "upload" ) ;
117
+
118
+ const denylistString = await fs . promises . readFile ( path . join ( __dirname , 'envVarDenylist.json' ) , 'utf8' ) ;
119
+ const denylist = JSON . parse ( denylistString ) ;
120
+
121
+ Object . keys ( process . env ) . forEach ( ( envVarKey : string ) => {
122
+ const envVarValue = process . env [ envVarKey ] ;
123
+
124
+ if ( envVarValue . includes ( "\n" ) ) {
125
+ tl . warning ( "Environment variable " + envVarKey + " is a multiline string and cannot be added to the build environment." ) ;
126
+ return ;
127
+ }
128
+
129
+ if ( systemVariableNames . has ( envVarKey ) ) {
130
+ tl . warning ( "custom variable overlapping with reserved SWA variable: " + envVarKey ) ;
131
+ return ;
132
+ }
133
+
134
+ if ( ! denylist . includes ( envVarKey . toUpperCase ( ) ) ) {
135
+ addVariableToString ( envVarKey , envVarValue ) ;
136
+ }
137
+ } ) ;
138
+
139
+ await fs . promises . writeFile ( envVarFilePath , variableString ) ;
140
+ }
141
+
142
+ function getNullableBooleanFromString ( boolString :string ) : boolean {
143
+ if ( boolString == null ) return null ;
144
+ boolString = boolString . toLowerCase ( ) ;
145
+
146
+ if ( boolString === "true" ) {
147
+ return true ;
51
148
}
52
- catch ( err ) {
53
- tl . setResult ( tl . TaskResult . Failed , null ) ;
149
+
150
+ if ( boolString === "false" ) {
151
+ return false ;
54
152
}
153
+
154
+ return null ;
55
155
}
56
156
57
157
run ( ) ;
0 commit comments