Skip to content

Commit da3c4fd

Browse files
committed
repo: Add gh-actions/fs/overlay
Signed-off-by: Ryan Northey <[email protected]>
1 parent 1cd3295 commit da3c4fd

File tree

3 files changed

+260
-0
lines changed

3 files changed

+260
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Test GCS FUSE Mount Action
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- 'actions-v*'
8+
paths:
9+
- 'gh-actions/gcs/fuse/**'
10+
- '.github/workflows/test-gcs-fuse.yml'
11+
pull_request:
12+
paths:
13+
- 'gh-actions/gcs/fuse/**'
14+
- '.github/workflows/test-gcs-fuse.yml'
15+
16+
jobs:
17+
test-external:
18+
name: Test anonymous access (fork PRs)
19+
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v4
23+
- uses: ./gh-actions/gcs/fuse
24+
with:
25+
bucket: gcp-public-data-sentinel-2
26+
mount-point: /tmp/gcs-public-test
27+
- run: |
28+
ls -la /tmp/gcs-public-test
29+
ls -la /tmp/gcs-public-test | grep -q index.csv
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Test Overlay with GCS FUSE Mount
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- 'actions-v*'
8+
paths:
9+
- 'gh-actions/fs/overlay/**'
10+
- 'gh-actions/gcs/fuse/**'
11+
- '.github/workflows/test-overlay-fuse.yml'
12+
pull_request:
13+
paths:
14+
- 'gh-actions/fs/overlay/**'
15+
- 'gh-actions/gcs/fuse/**'
16+
- '.github/workflows/test-overlay-fuse.yml'
17+
18+
jobs:
19+
test-overlay-public:
20+
name: Test overlay with public GCS bucket
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v4
24+
- name: Mount public GCS bucket
25+
uses: ./gh-actions/gcs/fuse
26+
with:
27+
bucket: gcp-public-data-sentinel-2
28+
mount-point: ${{ runner.temp }}/gcs-public
29+
- name: Create overlay directories
30+
run: |
31+
mkdir -p ${{ runner.temp }}/overlay-upper
32+
mkdir -p ${{ runner.temp }}/overlay-mount
33+
echo "Initial content in upper dir" > ${{ runner.temp }}/overlay-upper/upper-test-file.txt
34+
- name: Mount overlay filesystem
35+
uses: ./gh-actions/fs/overlay
36+
with:
37+
lower-dir: "${{ runner.temp }}/gcs-public"
38+
upper-dir: "${{ runner.temp }}/overlay-upper"
39+
mount-point: "${{ runner.temp }}/overlay-mount"
40+
- name: Verify GCS data visibility
41+
run: |
42+
ls -la "${{ runner.temp }}/overlay-mount"
43+
ls -la "${{ runner.temp }}/overlay-mount" | grep -q csv
44+
ls -la "${{ runner.temp }}/overlay-mount" | grep -q upper-test-file.txt
45+
- name: Test write operations
46+
run: |
47+
echo "This is a new file created in the overlay" > "${{ runner.temp }}/overlay-mount/new-file.txt"
48+
if [ -f "${{ runner.temp }}/overlay-mount/hello.txt" ]; then
49+
echo "APPENDED CONTENT" >> "${{ runner.temp }}/overlay-mount/hello.txt
50+
echo "✅ Successfully modified a GCS file through the overlay"
51+
cat "${{ runner.temp }}/overlay-mount/hello.txt
52+
fi
53+
if [ -f "${{ runner.temp }}/overlay-mount/new-file.txt" ] && [ ! -f "${{ runner.temp }}/gcs-public/new-file.txt" ]; then
54+
echo "✅ Write operations are working correctly"
55+
echo "✅ Original GCS mount remains unchanged"
56+
else
57+
echo "❌ Overlay write test failed"
58+
exit 1
59+
fi
60+
if [ -f "${{ runner.temp }}/overlay-upper/new-file.txt" ]; then
61+
echo "✅ Changes correctly stored in upper layer"
62+
cat ${{ runner.temp }}/overlay-upper/new-file.txt
63+
else
64+
echo "❌ Changes not properly stored in upper layer"
65+
exit 1
66+
fi

gh-actions/fs/overlay/action.yml

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
name: Overlay Filesystem Mount
2+
description: Create and mount an overlay filesystem to combine directories and allow writes to a read-only base
3+
author: Ryan Northey <[email protected]>
4+
5+
inputs:
6+
upper-dir:
7+
type: string
8+
required: true
9+
description: |
10+
Path to the directory that will contain the upper layer (write layer)
11+
lower-dir:
12+
type: string
13+
required: true
14+
description: |
15+
Path to the base directory (read-only layer) - can be a colon-separated list for multiple lower layers
16+
mount-point:
17+
type: string
18+
required: true
19+
description: |
20+
Directory path where the overlay filesystem will be mounted
21+
work-dir:
22+
type: string
23+
description: |
24+
Path to the directory used for overlay work files (created automatically if not specified)
25+
create-dirs:
26+
type: boolean
27+
default: true
28+
description: |
29+
Automatically create the upper, work, and mount directories if they don't exist
30+
options:
31+
type: string
32+
description: |
33+
Additional mount options for the overlay filesystem
34+
read-only:
35+
type: boolean
36+
default: false
37+
description: |
38+
Mount the overlay as read-only
39+
verify-mount:
40+
type: boolean
41+
default: true
42+
description: |
43+
Verify that the mount was successful
44+
debug:
45+
type: boolean
46+
default: false
47+
description: |
48+
Enable debug logging
49+
50+
outputs:
51+
mount-path:
52+
description: 'The full path where the overlay filesystem was mounted'
53+
value: ${{ steps.mount.outputs.mount-path }}
54+
55+
unmount-cmd:
56+
description: 'Command to unmount the overlay filesystem (for use in post cleanup)'
57+
value: ${{ steps.mount.outputs.unmount-cmd }}
58+
59+
runs:
60+
using: "composite"
61+
steps:
62+
- name: Check for overlay module
63+
shell: bash
64+
run: |
65+
if ! grep -q overlay /proc/filesystems; then
66+
echo "Overlay filesystem is not supported on this system!" >&2
67+
exit 1
68+
fi
69+
if [[ "${{ inputs.debug }}" == "true" ]]; then
70+
echo "Overlay filesystem is supported"
71+
fi
72+
73+
- name: Create required directories
74+
if: ${{ inputs.create-dirs == 'true' }}
75+
shell: bash
76+
run: |
77+
mkdir -p "${{ inputs.upper-dir }}"
78+
mkdir -p "${{ inputs.mount-point }}"
79+
80+
if [[ -n "${{ inputs.work-dir }}" ]]; then
81+
WORK_DIR="${{ inputs.work-dir }}"
82+
else
83+
WORK_DIR="${{ inputs.upper-dir }}-work"
84+
fi
85+
mkdir -p "$WORK_DIR"
86+
echo "OVERLAY_WORK_DIR=$WORK_DIR" >> $GITHUB_ENV
87+
if [[ "${{ inputs.debug }}" == "true" ]]; then
88+
echo "Created directories:"
89+
echo " Upper dir: ${{ inputs.upper-dir }}"
90+
echo " Mount point: ${{ inputs.mount-point }}"
91+
echo " Work dir: $WORK_DIR"
92+
fi
93+
94+
- uses: envoyproxy/toolshed/gh-actions/github/script/[email protected]
95+
name: Mount overlay filesystem
96+
id: mount
97+
with:
98+
run: |
99+
MOUNT_POINT="${{ inputs.mount-point }}"
100+
UPPER_DIR="${{ inputs.upper-dir }}"
101+
LOWER_DIR="${{ inputs.lower-dir }}"
102+
WORK_DIR="${OVERLAY_WORK_DIR}"
103+
MOUNT_OPTS="lowerdir=${LOWER_DIR},upperdir=${UPPER_DIR},workdir=${WORK_DIR}"
104+
if [[ -n "${{ inputs.options }}" ]]; then
105+
MOUNT_OPTS="${MOUNT_OPTS},${{ inputs.options }}"
106+
fi
107+
if [[ "${{ inputs.read-only }}" == "true" ]]; then
108+
MOUNT_OPTS="${MOUNT_OPTS},ro"
109+
fi
110+
if [[ "${{ inputs.debug }}" == "true" ]]; then
111+
echo "Mount options: $MOUNT_OPTS"
112+
fi
113+
114+
sudo ls -alh ${MOUNT_POINT}
115+
sudo ls -alh ${WORK_DIR}
116+
sudo ls -alh ${LOWER_DIR}
117+
sudo ls -alh ${UPPER_DIR}
118+
119+
ls -alh ${MOUNT_POINT}
120+
ls -alh ${WORK_DIR}
121+
ls -alh ${LOWER_DIR}
122+
ls -alh ${UPPER_DIR}
123+
124+
CMD="sudo mount -t overlay -o ${MOUNT_OPTS} overlay ${MOUNT_POINT}"
125+
echo "Mounting with: $CMD"
126+
sudo mount -t overlay -o ${MOUNT_OPTS} overlay ${MOUNT_POINT}
127+
RESULT=$?
128+
if [[ $RESULT -ne 0 ]]; then
129+
echo "Failed to mount overlay filesystem" >&2
130+
exit 1
131+
fi
132+
sudo mount
133+
sudo chown runner:runner ${MOUNT_POINT}
134+
sudo ls -alh ${MOUNT_POINT} || echo "root cant see"
135+
ls -alh ${MOUNT_POINT} || echo "runner cant see"
136+
echo "mount-path=${MOUNT_POINT}" >> $GITHUB_OUTPUT
137+
echo "unmount-cmd=umount ${MOUNT_POINT}" >> $GITHUB_OUTPUT
138+
post: |
139+
sudo umount ${{ inputs.mount-point }} || true
140+
141+
- name: Verify mount
142+
if: ${{ inputs.verify-mount == 'true' }}
143+
shell: bash
144+
run: |
145+
if ! mount | grep -q "${{ inputs.mount-point }} type overlay"; then
146+
echo "Overlay mount verification failed!" >&2
147+
exit 1
148+
fi
149+
150+
if [[ "${{ inputs.debug }}" == "true" ]]; then
151+
echo "Mount details:"
152+
mount | grep overlay
153+
echo "Filesystem contents:"
154+
ls -la "${{ inputs.mount-point }}"
155+
fi
156+
157+
- name: Mount information
158+
shell: bash
159+
run: |
160+
echo "Overlay filesystem mounted successfully"
161+
echo " Mount point: ${{ inputs.mount-point }}"
162+
echo " Upper dir: ${{ inputs.upper-dir }}"
163+
echo " Lower dir: ${{ inputs.lower-dir }}"
164+
echo " Work dir: ${{ env.OVERLAY_WORK_DIR }}"
165+
echo " Read-only: ${{ inputs.read-only }}"

0 commit comments

Comments
 (0)