1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
#include "delivery.h"
int delivery_init_artifactory(struct Delivery *ctx) {
int status = 0;
char dest[PATH_MAX] = {0};
char filepath[PATH_MAX] = {0};
snprintf(dest, sizeof(dest) - 1, "%s/bin", ctx->storage.tools_dir);
snprintf(filepath, sizeof(dest) - 1, "%s/bin/jf", ctx->storage.tools_dir);
if (!access(filepath, F_OK)) {
// already have it
msg(STASIS_MSG_L3, "Skipped download, %s already exists\n", filepath);
goto delivery_init_artifactory_envsetup;
}
char *platform = ctx->system.platform[DELIVERY_PLATFORM];
msg(STASIS_MSG_L3, "Downloading %s for %s %s\n", globals.jfrog.remote_filename, platform, ctx->system.arch);
if ((status = artifactory_download_cli(dest,
globals.jfrog.jfrog_artifactory_base_url,
globals.jfrog.jfrog_artifactory_product,
globals.jfrog.cli_major_ver,
globals.jfrog.version,
platform,
ctx->system.arch,
globals.jfrog.remote_filename))) {
remove(filepath);
}
delivery_init_artifactory_envsetup:
// CI (ridiculously generic, why?) disables interactive prompts and progress bar output
setenv("CI", "1", 1);
// JFROG_CLI_HOME_DIR is where .jfrog is stored
char path[PATH_MAX] = {0};
snprintf(path, sizeof(path) - 1, "%s/.jfrog", ctx->storage.build_dir);
setenv("JFROG_CLI_HOME_DIR", path, 1);
// JFROG_CLI_TEMP_DIR is where the obvious is stored
setenv("JFROG_CLI_TEMP_DIR", ctx->storage.tmpdir, 1);
return status;
}
int delivery_artifact_upload(struct Delivery *ctx) {
int status = 0;
if (jfrt_auth_init(&ctx->deploy.jfrog_auth)) {
fprintf(stderr, "Failed to initialize Artifactory authentication context\n");
return -1;
}
for (size_t i = 0; i < sizeof(ctx->deploy.jfrog) / sizeof(*ctx->deploy.jfrog); i++) {
if (!ctx->deploy.jfrog[i].files || !ctx->deploy.jfrog[i].dest) {
break;
}
jfrt_upload_init(&ctx->deploy.jfrog[i].upload_ctx);
if (!globals.jfrog.repo) {
msg(STASIS_MSG_WARN, "Artifactory repository path is not configured!\n");
fprintf(stderr, "set STASIS_JF_REPO environment variable...\nOr append to configuration file:\n\n");
fprintf(stderr, "[deploy:artifactory]\nrepo = example/generic/repo/path\n\n");
status++;
break;
} else if (!ctx->deploy.jfrog[i].repo) {
ctx->deploy.jfrog[i].repo = strdup(globals.jfrog.repo);
}
if (!ctx->deploy.jfrog[i].repo || isempty(ctx->deploy.jfrog[i].repo) || !strlen(ctx->deploy.jfrog[i].repo)) {
// Unlikely to trigger if the config parser is working correctly
msg(STASIS_MSG_ERROR, "Artifactory repository path is empty. Cannot continue.\n");
status++;
break;
}
ctx->deploy.jfrog[i].upload_ctx.workaround_parent_only = true;
ctx->deploy.jfrog[i].upload_ctx.build_name = ctx->info.build_name;
ctx->deploy.jfrog[i].upload_ctx.build_number = ctx->info.build_number;
char files[PATH_MAX];
char dest[PATH_MAX]; // repo + remote dir
if (jfrog_cli_rt_ping(&ctx->deploy.jfrog_auth)) {
msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "Unable to contact artifactory server: %s\n", ctx->deploy.jfrog_auth.url);
return -1;
}
if (strlist_count(ctx->deploy.jfrog[i].files)) {
for (size_t f = 0; f < strlist_count(ctx->deploy.jfrog[i].files); f++) {
memset(dest, 0, sizeof(dest));
memset(files, 0, sizeof(files));
snprintf(dest, sizeof(dest) - 1, "%s/%s", ctx->deploy.jfrog[i].repo, ctx->deploy.jfrog[i].dest);
snprintf(files, sizeof(files) - 1, "%s", strlist_item(ctx->deploy.jfrog[i].files, f));
status += jfrog_cli_rt_upload(&ctx->deploy.jfrog_auth, &ctx->deploy.jfrog[i].upload_ctx, files, dest);
}
}
}
if (globals.enable_artifactory_build_info) {
if (!status && ctx->deploy.jfrog[0].files && ctx->deploy.jfrog[0].dest) {
jfrog_cli_rt_build_collect_env(&ctx->deploy.jfrog_auth, ctx->deploy.jfrog[0].upload_ctx.build_name,
ctx->deploy.jfrog[0].upload_ctx.build_number);
jfrog_cli_rt_build_publish(&ctx->deploy.jfrog_auth, ctx->deploy.jfrog[0].upload_ctx.build_name,
ctx->deploy.jfrog[0].upload_ctx.build_number);
}
} else {
msg(STASIS_MSG_WARN | STASIS_MSG_L2, "Artifactory build info upload is disabled by CLI argument\n");
}
return status;
}
int delivery_mission_render_files(struct Delivery *ctx) {
if (!ctx->storage.mission_dir) {
fprintf(stderr, "Mission directory is not configured. Context not initialized?\n");
return -1;
}
struct Data {
char *src;
char *dest;
} data;
struct INIFILE *cfg = ctx->_stasis_ini_fp.mission;
union INIVal val;
memset(&data, 0, sizeof(data));
data.src = calloc(PATH_MAX, sizeof(*data.src));
if (!data.src) {
perror("data.src");
return -1;
}
for (size_t i = 0; i < cfg->section_count; i++) {
char *section_name = cfg->section[i]->key;
if (!startswith(section_name, "template:")) {
continue;
}
val.as_char_p = strchr(section_name, ':') + 1;
if (val.as_char_p && isempty(val.as_char_p)) {
guard_free(data.src);
return 1;
}
sprintf(data.src, "%s/%s/%s", ctx->storage.mission_dir, ctx->meta.mission, val.as_char_p);
msg(STASIS_MSG_L2, "%s\n", data.src);
int err = 0;
data.dest = ini_getval_str(cfg, section_name, "destination", INI_READ_RENDER, &err);
char *contents;
struct stat st;
if (lstat(data.src, &st)) {
perror(data.src);
guard_free(data.dest);
continue;
}
contents = calloc(st.st_size + 1, sizeof(*contents));
if (!contents) {
perror("template file contents");
guard_free(data.dest);
continue;
}
FILE *fp;
fp = fopen(data.src, "rb");
if (!fp) {
perror(data.src);
guard_free(contents);
guard_free(data.dest);
continue;
}
if (fread(contents, st.st_size, sizeof(*contents), fp) < 1) {
perror("while reading template file");
guard_free(contents);
guard_free(data.dest);
fclose(fp);
continue;
}
fclose(fp);
msg(STASIS_MSG_L3, "Writing %s\n", data.dest);
if (tpl_render_to_file(contents, data.dest)) {
guard_free(contents);
guard_free(data.dest);
continue;
}
guard_free(contents);
guard_free(data.dest);
}
guard_free(data.src);
return 0;
}
|