-
-
Notifications
You must be signed in to change notification settings - Fork 348
236 lines (222 loc) · 8.76 KB
/
test.yml
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
on: [push, pull_request]
name: Test
jobs:
test:
strategy:
matrix:
go-version: [1.21.x, 1.22.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: false
- run: go test ./...
- run: go test -race ./...
if: matrix.os == 'ubuntu-latest'
- run: GOARCH=386 go test -count=1 ./...
if: matrix.os == 'ubuntu-latest'
- name: confirm tests with Bash 5.2
run: |
go install mvdan.cc/dockexec@latest
CGO_ENABLED=0 go test -run TestRunnerRunConfirm -exec 'dockexec bash:5.2' ./interp
if: matrix.os == 'ubuntu-latest'
# Static checks from this point forward. Only run on one Go version and on
# Linux, since it's the fastest platform, and the tools behave the same.
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.22.x'
run: diff <(echo -n) <(gofmt -s -d .)
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.22.x'
run: go vet ./...
test-linux-alpine:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Test as root, without cgo, and with busybox
run: docker run -v="$PWD:/pwd" -w=/pwd -e=CGO_ENABLED=0 golang:1.22.0-alpine go test ./...
test-tinygo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Tinygo
uses: acifani/setup-tinygo@v2
- name: Create temporary main package
run: |
mkdir _tinygo && cat<<EOF > _tinygo/main.go
package main
import (
_ "mvdan.cc/sh/v3/expand"
_ "mvdan.cc/sh/v3/interp"
_ "mvdan.cc/sh/v3/syntax"
)
func main() {}
EOF
- name: Build with Tinygo natively
run: tinygo build -o /dev/null ./_tinygo
- name: Build with Tinygo on WASM
run: tinygo build -o /dev/null -target wasm ./_tinygo
docker:
name: Build and test Docker images
# Only deploy if previous stages pass.
needs: [test, test-linux-alpine]
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
# this is needed because we restart the docker daemon for experimental
# support
options: "--restart always"
env:
# Export environment variables for all stages.
DOCKER_USER: ${{ secrets.DOCKER_USER }}
DOCKER_DEPLOY_IMAGES: false
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
DOCKER_REPO: shfmt
# We use all platforms for which FROM images in our Dockerfile are
# available.
DOCKER_PLATFORMS: >
linux/386
linux/amd64
linux/arm/v7
linux/arm64/v8
linux/ppc64le
# linux/s390x TODO: reenable when we figure out its weird errors when
# fetching dependencies, including:
#
# zip: checksum error
# Get "https://proxy.golang.org/...": local error: tls: bad record MAC
# Get "https://proxy.golang.org/...": local error: tls: unexpected message
# Get "https://proxy.golang.org/...": x509: certificate signed by unknown authority
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # also fetch tags for 'git describe'
# Enable docker daemon experimental support (for 'pull --platform').
- name: Enable experimental support
run: |
config='/etc/docker/daemon.json'
if [[ -e "$config" ]]; then
sudo sed -i -e 's/{/{ "experimental": true, /' "$config"
else
echo '{ "experimental": true }' | sudo tee "$config"
fi
sudo systemctl restart docker
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
- name: Set up env vars
run: |
set -vx
# Export environment variable for later stages.
if echo "$GITHUB_REF" | grep -q '^refs/heads/master$'; then
# Pushes to the master branch deploy 'latest'.
echo "TAG=latest" >> $GITHUB_ENV
elif echo "$GITHUB_REF" | grep -q '^refs/heads/docker-push-test$'; then
# Pushes to the test branch deploy 'latest-test'.
echo "TAG=latest-test" >> $GITHUB_ENV
elif echo "$GITHUB_REF" | grep -q '^refs/tags/'; then
# Pushes to a git tag use it as the docker tag.
echo "TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
else
# Otherwise, we build and test the image locally, but we don't push it.
echo "TAG=${GITHUB_SHA::8}" >> $GITHUB_ENV
fi
echo "DOCKER_BASE=test/${{ env.DOCKER_REPO }}" >> $GITHUB_ENV
echo "DOCKER_BUILD_PLATFORMS=${DOCKER_PLATFORMS// /,}" >> $GITHUB_ENV
- name: Build and push to local registry
uses: docker/build-push-action@v5
with:
provenance: false # temporarily work around https://github.com/containers/skopeo/issues/1874
context: .
file: ./cmd/shfmt/Dockerfile
platforms: ${{ env.DOCKER_BUILD_PLATFORMS }}
push: true
tags: localhost:5000/${{ env.DOCKER_BASE }}:${{ env.TAG }}
- name: Build and push to local registry (alpine)
uses: docker/build-push-action@v5
with:
provenance: false # temporarily work around https://github.com/containers/skopeo/issues/1874
context: .
file: ./cmd/shfmt/Dockerfile
platforms: ${{ env.DOCKER_BUILD_PLATFORMS }}
push: true
tags: localhost:5000/${{ env.DOCKER_BASE }}:${{ env.TAG }}-alpine
target: alpine
- name: Test multi-arch Docker images locally
run: |
for platform in $DOCKER_PLATFORMS; do
for ext in '' '-alpine'; do
image="localhost:5000/${DOCKER_BASE}:${TAG}${ext}"
msg="Testing docker image $image on platform $platform"
line="${msg//?/=}"
printf "\n${line}\n${msg}\n${line}\n"
docker pull -q --platform "$platform" "$image"
if [[ -n "$ext" ]]; then
echo -n "Image architecture: "
docker run --rm --entrypoint /bin/sh "$image" -c 'uname -m'
fi
version=$(docker run --rm "$image" --version)
echo "shfmt version: $version"
if [[ $TAG != "latest" ]] &&
[[ $TAG != "latest-test" ]] &&
[[ $TAG != "$version" ]] &&
! echo "$version" | grep -q "$TAG"; then
echo "Version mismatch: shfmt $version tagged as $TAG"
exit 1
fi
docker run --rm -v "$PWD:/mnt" -w '/mnt' "$image" -d cmd/shfmt/docker-entrypoint.sh
done
done
- name: Check GitHub settings
if: >
github.event_name == 'push' &&
github.repository == 'mvdan/sh' &&
(github.ref == 'refs/heads/master' ||
github.ref == 'refs/heads/docker-push-test' ||
startsWith(github.ref, 'refs/tags/'))
run: |
missing=()
[[ -n "${{ secrets.DOCKER_USER }}" ]] || missing+=(DOCKER_USER)
[[ -n "${{ secrets.DOCKER_TOKEN }}" ]] || missing+=(DOCKER_TOKEN)
for i in "${missing[@]}"; do
echo "Missing github secret: $i"
done
(( ${#missing[@]} == 0 )) || exit 1
echo "DOCKER_DEPLOY_IMAGES=true" >> $GITHUB_ENV
- name: Login to DockerHub
if: ${{ env.DOCKER_DEPLOY_IMAGES == 'true' }}
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Push images to DockerHub
if: ${{ env.DOCKER_DEPLOY_IMAGES == 'true' }}
run: |
for ext in '' '-alpine'; do
image_src="${DOCKER_BASE}:${TAG}${ext}"
image_dsts=("${{ secrets.DOCKER_USER }}/${{ env.DOCKER_REPO }}:${TAG}${ext}")
if echo $TAG | grep -q '^v3\.[0-9]\+\.[0-9]\+$'; then
image_dsts+=("${{ secrets.DOCKER_USER }}/${{ env.DOCKER_REPO }}:v3${ext}")
elif [[ $TAG == latest-test ]]; then
image_dsts+=("${{ secrets.DOCKER_USER }}/${{ env.DOCKER_REPO }}:v3-test${ext}")
fi
# Show what we're doing.
msg="Copy multi-arch docker images to DockerHub ($image_src with ${#image_dsts[@]} destinations)"
line="${msg//?/=}"
printf "\n${line}\n${msg}\n${line}\n"
for image_dst in "${image_dsts[@]}"; do
skopeo copy --all --src-tls-verify=0 docker://localhost:5000/$image_src docker://docker.io/$image_dst
done
done
- name: Update DockerHub description
if: ${{ env.DOCKER_DEPLOY_IMAGES == 'true' }}
uses: peter-evans/dockerhub-description@v4
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
repository: ${{ secrets.DOCKER_USER }}/${{ env.DOCKER_REPO }}
readme-filepath: README.md