Skip to content

Commit 42ee355

Browse files
Merge pull request #2507 from FarmBot/staging
v15.22.0
2 parents a6c03ff + 6956226 commit 42ee355

909 files changed

Lines changed: 34428 additions & 18060 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 246 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,81 @@ executors:
88
working_directory: /home/circleci/project
99

1010
commands:
11-
build-commands:
11+
start-commands:
1212
steps:
13-
- checkout
14-
- restore_cache:
15-
keys:
16-
- cache-v1-{{ .Revision }}-{{ .Environment.CIRCLE_WORKFLOW_ID }}
13+
- send-notification:
14+
message: "CI run started"
15+
- send-notification:
16+
message: "<${CIRCLE_BUILD_URL}|logs>"
1717
- run:
18-
name: After cache restore
18+
name: Create compare link
1919
command: |
20-
git clean -xdn
21-
mkdir -p docker_cache
22-
ls docker_cache
23-
#sudo docker images
24-
#if [ -f docker_cache/images.tar.gz ]; then gunzip -c docker_cache/images.tar.gz | sudo docker load; fi
20+
DEPLOYS_URL_API="https://api.github.com/repos/Farmbot/Farmbot-Web-App/deployments"
21+
COMPARE_URL_WEB="https://github.com/Farmbot/Farmbot-Web-App/compare/"
22+
data=$(curl -fsS "$DEPLOYS_URL_API") || data="[]"
23+
last_sha=$(printf "%s" "$data" | python -c 'import json,sys; data=json.loads(sys.stdin.read() or "[]"); deploy_index=0; sha=(data[deploy_index] or {}).get("sha"); print(sha or "")')
24+
compare_url="$COMPARE_URL_WEB$last_sha...${CIRCLE_SHA1}"
25+
echo "$compare_url"
26+
echo "export COMPARE_URL='$compare_url'" >> "$BASH_ENV"
27+
- send-notification:
28+
message: "<$COMPARE_URL|diff>"
29+
send-notification:
30+
parameters:
31+
message:
32+
type: string
33+
when:
34+
type: enum
35+
enum: ["on_success", "on_fail", "always"]
36+
default: "always"
37+
steps:
38+
- when:
39+
condition:
40+
equal: [staging, << pipeline.git.branch >>]
41+
steps:
42+
- run:
43+
name: "Send notification: << parameters.message >>"
44+
when: << parameters.when >>
45+
command: |
46+
if [ -n "$SLACK_WEBHOOK_URL" ]; then
47+
curl -fsS -X POST -H "Content-Type: application/json" \
48+
--data "{\"text\":\"<< parameters.message >>\",\"channel\":\"#software\"}" \
49+
"$SLACK_WEBHOOK_URL" || true
50+
fi
51+
build-commands:
52+
steps:
2553
- run:
2654
name: Build and Install Deps
2755
command: |
2856
mv .circleci/circle_envs .env
2957
echo -e '\ndocker_volumes/db/pg_wal/*' >> .dockerignore
3058
sudo docker compose build web
31-
sudo docker compose run web gem install bundler
32-
sudo docker compose run web bundle install
33-
sudo docker compose run web npm install
34-
sudo docker compose run web bundle exec rails db:create
35-
sudo docker compose run web bundle exec rails db:migrate
36-
sudo docker compose run web bundle exec rake keys:generate
37-
- run:
38-
name: After cache update
39-
command: |
40-
mkdir -p /tmp/test-results
41-
git clean -xdn
42-
ls docker_cache
43-
#sudo docker images
44-
#if [ ! -f docker_cache/images.tar.gz ]; then sudo docker save $(sudo docker images ruby -q) | gzip > docker_cache/images.tar.gz; fi
45-
# - save_cache:
46-
# key: cache-v1-{{ .Revision }}-{{ .Environment.CIRCLE_WORKFLOW_ID }}
47-
# paths:
48-
# - docker_volumes
49-
# - node_modules
50-
# - docker_cache
59+
if sudo docker compose run --rm web bash -lc '\
60+
gem install bundler && \
61+
bundle install && \
62+
bun install && \
63+
bundle exec rails db:create && \
64+
bundle exec rails db:migrate && \
65+
bundle exec rake keys:generate \
66+
'; then
67+
echo "export SETUP_OK=true" >> "$BASH_ENV"
68+
else
69+
echo "export SETUP_OK=false" >> "$BASH_ENV"
70+
exit 1
71+
fi
5172
rspec-commands:
5273
steps:
5374
- run:
5475
name: Run Ruby Tests
5576
command: |
56-
sudo docker compose run web bundle exec rspec spec --format progress --format RspecJunitFormatter --out /tmp/test-results/rspec/rspec.xml
77+
sudo docker compose run --rm web bundle exec rspec spec --format progress --format RspecJunitFormatter --out test-results/rspec.xml
5778
- run:
5879
name: Check app coverage status
5980
command: |
60-
sudo docker compose run web bundle exec rake check_file_coverage:api || [ $CIRCLE_BRANCH == "staging" ]
81+
if [ "$SETUP_OK" != "true" ]; then
82+
echo "skipping"
83+
exit 0
84+
fi
85+
sudo docker compose run --rm web bundle exec rake check_file_coverage:api || [ $CIRCLE_BRANCH == "staging" ]
6186
when: always
6287
- run:
6388
name: Upload app coverage to Codecov
@@ -70,32 +95,59 @@ commands:
7095
shasum -a 256 -c codecov.SHA256SUM
7196
chmod +x codecov
7297
./codecov -t $CODECOV_TOKEN -f coverage_api/coverage.xml
73-
jest-commands:
98+
js-test-commands:
7499
steps:
75100
- run:
76101
name: Run JS tests
77102
command: |
78-
sudo docker compose run web npm run test-slow -- -c .circleci/jest-ci.config.js -w 6
103+
sudo docker compose run --rm web bun test --reporter=junit --reporter-outfile=test-results/junit.xml
79104
echo 'export COVERAGE_AVAILABLE=true' >> $BASH_ENV
80105
lint-commands:
81106
steps:
82107
- run:
83108
name: Run JS Linters
84109
command: |
85-
sudo docker compose run web npm run linters
110+
if [ "$SETUP_OK" != "true" ]; then
111+
echo "skipping"
112+
exit 0
113+
fi
114+
sudo docker compose run --rm web bun run linters
115+
when: always
116+
bun-build-commands:
117+
steps:
118+
- run:
119+
name: Check bun build
120+
command: |
121+
if [ "$SETUP_OK" != "true" ]; then
122+
echo "skipping"
123+
exit 0
124+
fi
125+
sudo docker compose run --rm web bundle exec rake assets:precompile 2>&1 | tee assets_precompile.log
126+
printf -- '-%.0s' {1..50}; printf '\n'
127+
if grep -Ei '^(warn|error):' assets_precompile.log; then
128+
exit 1
129+
fi
86130
when: always
87131
coverage-commands:
88132
steps:
89133
- run:
90134
name: Check frontend coverage status
91135
command: |
92-
sudo docker compose run -e CIRCLE_SHA1="$CIRCLE_SHA1" -e CIRCLE_BRANCH="$CIRCLE_BRANCH" -e CIRCLE_PULL_REQUEST="$CIRCLE_PULL_REQUEST" web bundle exec rake coverage:run || [ $CIRCLE_BRANCH == "staging" ]
136+
if [ "$SETUP_OK" != "true" ]; then
137+
echo "skipping"
138+
exit 0
139+
fi
140+
sudo docker compose run --rm -e CIRCLE_SHA1="$CIRCLE_SHA1" -e CIRCLE_BRANCH="$CIRCLE_BRANCH" -e CIRCLE_PULL_REQUEST="$CIRCLE_PULL_REQUEST" web bundle exec rake coverage:run || [ $CIRCLE_BRANCH == "staging" ]
93141
when: always
94142
- run:
95143
name: Check frontend file coverage status
96144
command: |
145+
if [ "$SETUP_OK" != "true" ]; then
146+
echo "skipping"
147+
exit 0
148+
fi
97149
changed=$(git diff --name-only staging...HEAD | tr '\n' ',' | sed 's/,$//') || true
98-
sudo docker compose run -e CHANGED_FILES="$changed" web bundle exec rake check_file_coverage:fe || true
150+
sudo docker compose run --rm -e CHANGED_FILES="$changed" web bundle exec rake check_file_coverage:fe || true
99151
when: always
100152
- run:
101153
name: Report frontend coverage to Coveralls
@@ -111,61 +163,176 @@ commands:
111163
fi
112164
if [ "$CIRCLE_BRANCH" == "staging" ]; then echo; fi
113165
when: always # change to `on_success` for a stricter comparison
166+
render-commands:
167+
steps:
168+
- run:
169+
name: Start services
170+
when: always
171+
command: |
172+
if [ "$SETUP_OK" != "true" ]; then
173+
echo "skipping"
174+
exit 0
175+
fi
176+
sudo docker compose up -d
177+
sudo docker compose ps
178+
- run:
179+
name: Install playwright
180+
when: always
181+
command: |
182+
if [ "$SETUP_OK" != "true" ]; then
183+
echo "skipping"
184+
exit 0
185+
fi
186+
sudo docker compose exec -e PLAYWRIGHT_BROWSERS_PATH=0 web bunx playwright install chromium --with-deps
187+
- run:
188+
name: Wait for load
189+
when: always
190+
command: |
191+
if [ "$SETUP_OK" != "true" ]; then
192+
echo "skipping"
193+
exit 0
194+
fi
195+
for i in $(seq 1 90); do
196+
if curl -fsS "http://127.0.0.1:3000/promo" >/dev/null; then
197+
echo "web is up"
198+
exit 0
199+
fi
200+
sleep 2
201+
done
202+
203+
echo "timeout"
204+
sudo docker compose logs --no-color --tail=300 web
205+
exit 1
206+
- run:
207+
name: Run playwright
208+
when: always
209+
command: |
210+
if [ "$SETUP_OK" != "true" ]; then
211+
echo "skipping"
212+
exit 0
213+
fi
214+
attempts=2
215+
for _ in $(seq 1 "$attempts"); do
216+
url="http://localhost:3000/promo?sizePreset=Genesis+XL&promoSpread=true"
217+
echo "Attempting FPS check via ${url}"
218+
if ! sudo docker compose exec web curl -I "${url}" >/dev/null; then
219+
continue
220+
fi
221+
222+
if ! fps_output=$(sudo docker compose exec -e PLAYWRIGHT_BROWSERS_PATH=0 web bun scripts/fps.js "${url}" "tmp/promo.png"); then
223+
echo "${fps_output}"
224+
continue
225+
fi
226+
echo "${fps_output}"
227+
228+
fps_value=$(echo "${fps_output}" | awk -F= '/^FPS_VALUE=/{print $2; exit}')
229+
scene_metrics=$(echo "${fps_output}" | awk -F= '/^SCENE_METRICS=/{print $2; exit}')
230+
echo "export FPS_VALUE=${fps_value}" >> "$BASH_ENV"
231+
echo "export SCENE_METRICS=\"${scene_metrics}\"" >> "$BASH_ENV"
232+
233+
exit 0
234+
done
235+
236+
echo "FPS check failed for all URLs"
237+
exit 1
238+
- restore_cache:
239+
keys:
240+
- fps_value-staging-
241+
- run:
242+
name: Load previous value
243+
when: always
244+
command: |
245+
if [ -f fps_value.txt ]; then
246+
PREV=$(cat fps_value.txt)
247+
else
248+
PREV=0.75
249+
fi
250+
echo "Previous value: $PREV fps"
251+
echo "export PREV_VALUE=$PREV" >> $BASH_ENV
252+
- run:
253+
name: Compare value
254+
when: always
255+
command: |
256+
percent_change=$(python -c 'import os; fps=float(os.environ.get("FPS_VALUE","0") or 0); prev=float(os.environ.get("PREV_VALUE","0") or 0); print("n/a" if prev==0 else f"{((fps-prev)/prev)*100:.2f}")')
257+
echo "$FPS_VALUE fps ($percent_change% change)"
258+
echo "export PERCENT_CHANGE=$percent_change" >> "$BASH_ENV"
259+
- run:
260+
name: Save new value
261+
command: |
262+
echo "$FPS_VALUE"
263+
echo "$FPS_VALUE" > fps_value.txt
264+
if [ ! -f scene_metrics.csv ]; then
265+
printf '%s\n' "epoch, FPS, Calls, Triangles, Points, Lines, Geometries, Textures, Objects, Meshes, Instanced meshes" > scene_metrics.csv
266+
fi
267+
printf '%s\n' "$SCENE_METRICS" >> scene_metrics.csv
268+
cat scene_metrics.csv
269+
- save_cache:
270+
key: fps_value-{{ .Branch }}-{{ epoch }}
271+
paths:
272+
- fps_value.txt
273+
- scene_metrics.csv
274+
- send-notification:
275+
message: "$FPS_VALUE fps (${PERCENT_CHANGE}% change)"
276+
- run:
277+
name: On failure
278+
when: on_fail
279+
command: |
280+
if [ "$SETUP_OK" != "true" ]; then
281+
echo "setup failed"
282+
exit 0
283+
fi
284+
sudo docker compose ps
285+
sudo docker compose logs --no-color --tail=500
286+
- store_artifacts:
287+
path: tmp/promo.png
288+
destination: promo_xl.png
289+
- store_artifacts:
290+
path: scene_metrics.csv
291+
destination: scene_metrics.csv
292+
end-commands:
293+
steps:
294+
- run:
295+
name: Fetch first artifact URL
296+
command: |
297+
project_slug="gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}"
298+
artifacts_json=$(curl -fsS \
299+
-H "Accept: application/json" \
300+
"https://circleci.com/api/v2/project/${project_slug}/${CIRCLE_BUILD_NUM}/artifacts")
301+
artifact_url=$(printf "%s" "$artifacts_json" | python -c 'import json,sys; data=json.load(sys.stdin); items=data.get("items") or []; print(items[0].get("url","") if items else "")')
302+
echo "export ARTIFACT_URL=$artifact_url" >> "$BASH_ENV"
303+
- send-notification:
304+
message: "CI run succeeded"
305+
when: on_success
306+
- send-notification:
307+
message: "<$ARTIFACT_URL|screenshot>"
308+
when: on_success
309+
- send-notification:
310+
message: "CI run failed"
311+
when: on_fail
312+
114313

115314

116315
workflows:
117316
version: 2
118317
build_and_test:
119-
max_auto_reruns: 1
318+
# max_auto_reruns: 1
120319
jobs:
121-
#- build
122320
- all
123-
#- test-api:
124-
# requires:
125-
# - build
126-
#- run-linters:
127-
# requires:
128-
# - build
129-
#- test-fe:
130-
# requires:
131-
# - build
132321

133322
jobs:
134-
build:
135-
executor: build-executor
136-
steps:
137-
- build-commands
138323
all:
139324
executor: build-executor
140325
steps:
326+
- start-commands
327+
- checkout
328+
- run: mkdir -p test-results
141329
- build-commands
142330
- rspec-commands
143331
- lint-commands
144-
- jest-commands
332+
- bun-build-commands
333+
- js-test-commands
145334
- store_test_results:
146-
path: /tmp/test-results
335+
path: test-results
147336
- coverage-commands
148-
test-api:
149-
executor: build-executor
150-
steps:
151-
- build-commands
152-
- rspec-commands
153-
- store_test_results:
154-
path: /tmp/test-results
155-
run-linters:
156-
executor: build-executor
157-
steps:
158-
- build-commands
159-
- lint-commands
160-
test-fe:
161-
executor: build-executor
162-
parallelism: 4
163-
steps:
164-
- build-commands
165-
- run:
166-
name: Run JS Tests
167-
command: |
168-
circleci tests glob **/__tests__/**/*.ts* | circleci tests split > /tmp/tests-to-run
169-
sudo docker compose run web npm run test-very-slow -- -c .circleci/jest-ci.config.js $(cat /tmp/tests-to-run)
170-
- store_test_results:
171-
path: /tmp/test-results
337+
- render-commands
338+
- end-commands

0 commit comments

Comments
 (0)