@@ -52,6 +52,8 @@ func NoOpStep(originalStep Step) Step {
5252// The original step must use the `google-github-actions/upload-cloud-storage` action
5353// and have valid "path" and "destination" inputs.
5454// If those conditions are not met, an error is returned.
55+ // The "parent" input (optional) is also handled and mimics the behavior of the original action.
56+ // The "glob" input (optional) filters which files to upload using a glob pattern (e.g., "*.txt", "**/*.json").
5557func MockGCSUploadStep (originalStep Step ) (Step , error ) {
5658 // Make sure the original step is indeed a GCS upload step
5759 if ! strings .HasPrefix (originalStep .Uses , GCSUploadAction ) {
@@ -66,26 +68,109 @@ func MockGCSUploadStep(originalStep Step) (Step, error) {
6668 return Step {}, fmt .Errorf ("could not mock gcs step %q (id: %q) because inputs are not valid" , originalStep .Name , originalStep .ID )
6769 }
6870
69- return Step {
70- Name : originalStep .Name + " (mocked)" ,
71- Run : Commands {
72- "set -x" ,
73- `mkdir -p /gcs/` + destPath ,
74- "cp -r " + srcPath + " /gcs/" + destPath ,
71+ // Glob input is optional, empty string means no filtering (copy all files).
72+ globPattern := ""
73+ if v , ok := originalStep .With ["glob" ].(string ); ok {
74+ globPattern = v
75+ }
76+
77+ // Parent input is optional, default to true.
78+ // If false, the contents of the folder are copied, but not the folder itself.
79+ // If true, the folder (including itself) is copied.
80+ // This mimics the behavior of the original Google Cloud Storage upload action.
81+ parent := true
82+ if v , ok := originalStep .With ["parent" ].(bool ); ok {
83+ parent = v
84+ }
85+ // Handle folder copying behavior:
86+ // - parent=true: copy the folder (including itself), e.g., cp src/folder dest → dest/folder/...
87+ // - parent=false: copy the contents of the folder (without the folder itself), e.g., cp src/folder/. dest → dest/...
88+ var folderCpCmdSuffix string
89+ var folderNameForOutput string
90+ if parent {
91+ // No special handling for cp. Copy the folder itself, recursively.
92+ folderCpCmdSuffix = ""
93+ // Include the folder name in the files list.
94+ // MUST have a trailing slash in the output name (for sed).
95+ folderNameForOutput = filepath .Base (srcPath ) + "/"
96+ } else {
97+ // Copy the contents of the folder, without the folder itself.
98+ folderCpCmdSuffix = "/."
99+ // No folder in output name. The content is copied, not the folder itself.
100+ folderNameForOutput = ""
101+ }
75102
76- // For debugging
77- "echo 'Mock GCS upload complete. Mock GCS bucket content:'" ,
78- "find /gcs -type f" ,
79- "cd " + srcPath ,
103+ // Build the bash commands based on whether glob is provided
104+ var commands Commands
105+ commands = append (commands ,
106+ "set -x" ,
107+ `mkdir -p /gcs/${DEST_PATH}` ,
80108
109+ // Handle both file and directory srcPath
110+ `if [ -f "${SRC_PATH}" ]; then` ,
111+ // srcPath is a file: copy directly (glob doesn't apply to single files)
112+ ` cp "${SRC_PATH}" /gcs/${DEST_PATH}/` ,
113+ ` filename=$(basename "${SRC_PATH}")` ,
114+ ` files="${DEST_PATH}/${filename}"` ,
115+ ` files=$(echo "$files" | cut -d'/' -f2-)` ,
116+ `else` ,
117+ // srcPath is a directory
118+ ` cd "${SRC_PATH}"` ,
119+ )
120+
121+ if globPattern != "" {
122+ // Glob mode: copy only files matching the pattern
123+ // - globstar enables ** to match directories recursively
124+ // - nullglob makes the pattern expand to nothing if no files match (avoids literal pattern in output)
125+ commands = append (commands ,
126+ ` shopt -s globstar nullglob` ,
127+ ` files=""` ,
128+ ` for file in ${GLOB_PATTERN}; do` ,
129+ ` if [ -f "$file" ]; then` ,
130+ // Create target directory preserving structure, then copy the file
131+ ` target_dir="/gcs/${DEST_PATH}/${FOLDER_NAME}$(dirname "$file")"` ,
132+ ` mkdir -p "$target_dir"` ,
133+ ` cp "$file" "$target_dir/"` ,
134+ // Build the files list (comma-separated)
135+ ` rel_path="${DEST_PATH}/${FOLDER_NAME}${file}"` ,
136+ ` rel_path=$(echo "$rel_path" | cut -d'/' -f2-)` ,
137+ ` if [ -n "$files" ]; then files="$files,"; fi` ,
138+ ` files="$files$rel_path"` ,
139+ ` fi` ,
140+ ` done` ,
141+ )
142+ } else {
143+ // Original behavior: copy all files recursively
144+ // if parent is true, copy the folder (including itself)
145+ // if parent is false, copy the contents of the folder (without the folder itself)
146+ commands = append (commands ,
147+ ` cp -r "${SRC_PATH}` + folderCpCmdSuffix + `" /gcs/${DEST_PATH}` ,
81148 // Get a list of all uploaded files, separated by commas.
82- // Find all files, prepend destPath, remove leading ./, get relative path (remove bucket name after `/gcs`), join with commas
83- `files=$(find . -type f | sed 's|^\./|` + destPath + `/|' | cut -d'/' -f2- | tr '\n' ',' | sed 's/,$//')` ,
149+ // Find all files, prepend destPath (and folder name if parent=true), remove leading ./, get relative path (remove bucket name after `/gcs`), join with commas
150+ ` files=$(find . -type f | sed "s|^\./|${DEST_PATH}/` + folderNameForOutput + `|" | cut -d'/' -f2- | tr '\n' ',' | sed 's/,$//')` ,
151+ )
152+ }
84153
85- // Set output (simplified)
86- `echo "uploaded=$files" >> "$GITHUB_OUTPUT"` ,
87- }.String (),
154+ commands = append (commands ,
155+ `fi` ,
156+ // For debugging
157+ "echo 'Mock GCS upload complete. Mock GCS bucket content:'" ,
158+ "find /gcs -type f" ,
159+ // Set output (simplified)
160+ `echo "uploaded=$files" >> "$GITHUB_OUTPUT"` ,
161+ )
162+
163+ return Step {
164+ // TODO: remove so it's handled by mockedName(), in other WIP PR
165+ Name : originalStep .Name + " (mocked)" ,
166+ Run : commands .String (),
88167 Shell : "bash" ,
168+ Env : map [string ]string {
169+ "SRC_PATH" : srcPath ,
170+ "DEST_PATH" : destPath ,
171+ "GLOB_PATTERN" : globPattern ,
172+ "FOLDER_NAME" : folderNameForOutput ,
173+ },
89174 }, nil
90175}
91176
0 commit comments