that allows ${VAR_NAME} variables to be expanded at runtime.
(cmd string)
| 139 | |
| 140 | // that allows ${VAR_NAME} variables to be expanded at runtime. |
| 141 | func buildDockerCommandWithExpandableVars(cmd string) string { |
| 142 | shellLog.Printf("Building docker command with expandable vars (length: %d)", len(cmd)) |
| 143 | // Find all ${VAR_NAME} patterns that need expansion outside of single quotes. |
| 144 | // We want: 'docker run ... -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ...' |
| 145 | // This closes the single quote, adds the variable in double quotes, then reopens single quote. |
| 146 | |
| 147 | // Collect all unique variable references |
| 148 | expandableVars := findExpandableVars(cmd) |
| 149 | |
| 150 | if len(expandableVars) == 0 { |
| 151 | shellLog.Print("No expandable variables found, using normal escaping") |
| 152 | return shellEscapeArg(cmd) |
| 153 | } |
| 154 | |
| 155 | shellLog.Printf("Docker command built with expandable variables: %v", expandableVars) |
| 156 | |
| 157 | // Process the command: wrap in single quotes, break out for each variable |
| 158 | var result strings.Builder |
| 159 | result.WriteString("'") |
| 160 | remaining := cmd |
| 161 | for len(remaining) > 0 { |
| 162 | // Find the next variable reference |
| 163 | nextIdx := -1 |
| 164 | nextVar := "" |
| 165 | for _, v := range expandableVars { |
| 166 | idx := strings.Index(remaining, v) |
| 167 | if idx >= 0 && (nextIdx < 0 || idx < nextIdx) { |
| 168 | nextIdx = idx |
| 169 | nextVar = v |
| 170 | } |
| 171 | } |
| 172 | if nextIdx < 0 { |
| 173 | // No more variables, write the rest |
| 174 | escapedPart := strings.ReplaceAll(remaining, "'", "'\\''") |
| 175 | result.WriteString(escapedPart) |
| 176 | break |
| 177 | } |
| 178 | // Write text before the variable |
| 179 | before := remaining[:nextIdx] |
| 180 | escapedBefore := strings.ReplaceAll(before, "'", "'\\''") |
| 181 | result.WriteString(escapedBefore) |
| 182 | // Break out of single quotes, add variable in double quotes, reopen single quotes |
| 183 | result.WriteString("'\"" + nextVar + "\"'") |
| 184 | remaining = remaining[nextIdx+len(nextVar):] |
| 185 | } |
| 186 | result.WriteString("'") |
| 187 | return result.String() |
| 188 | } |
| 189 | |
| 190 | // findExpandableVars returns all unique ${VAR_NAME} patterns in the string. |
| 191 | // It intentionally skips ${{ }} GitHub Actions expressions: those are evaluated |