################################################################################ ### STAGES stages: - prepare - build - tests - distrib - compatibility - release - publish ################################################################################ ### DEFAULT JOB PARAMETERS default: interruptible: true tags: [ nix-v2 ] ################################################################################ ### VARIABLES variables: DEFAULT: "master" OCAML: "4.14" NODE: "22" PUBLISH: "no" RELEASE: "no" ################################################################################ ### ONLY/EXCEPT TEMPLATES .build_template: &manual_when_not_special_pipeline except: refs: - schedules variables: - $RELEASE == "yes" when: manual .build_template: &when_release only: variables: - $RELEASE == "yes" .build_template: &when_schedules only: refs: - schedules .build_template: &when_publish only: variables: - $PUBLISH == "yes" ################################################################################ ### IVETTE SETUP TEMPLATE .build_template: &ivette_setup image: "ocaml/opam:ubuntu-lts-ocaml-$OCAML" before_script: # Prepare - sudo apt update # TS - sudo apt install -y xvfb curl unzip libnss3 libasound2-plugins - sudo curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash - export NVM_DIR="$HOME/.nvm" - . "$NVM_DIR/nvm.sh" - nvm install $NODE - nvm use node $NODE - corepack enable # Opam - opam switch create --empty . - eval $(opam env --switch=. --set-switch) - opam pin . -n -k path - opam depext frama-c - opam install headache - opam install --jobs 2 --deps-only . # Build Frama-C API - dune build -j2 @install - make -C ivette api ################################################################################ ### PREPARE check-makefile: stage: prepare script: - ./nix/shell-checkers.sh "make --warn-undefined-variables help > /dev/null 2> errors && [[ "$(cat errors)" == "" ]]" check-no-old-frama-c: stage: prepare script: - (! git merge-base --is-ancestor a1e186c68a6418a53b3dc06237f49e8dcbf75f4a HEAD) - git merge-base --is-ancestor a35d2118fe6999dddce9e1847eff626fae9cc37c HEAD .build_template: &do_not_stop_pipeline_template stage: prepare interruptible: false script: - echo "This pipeline won't be interrupted" unstoppable-pipeline: <<: *do_not_stop_pipeline_template only: variables: - $DEFAULT == $CI_COMMIT_BRANCH do-not-stop-pipeline: <<: *do_not_stop_pipeline_template when: manual except: variables: - $DEFAULT == $CI_COMMIT_BRANCH check-publish: stage: prepare script: > [[ "$RELEASE" == "no" ]] && [[ "$DEFAULT" == "$CI_COMMIT_BRANCH" ]] && [[ "$DEFAULT" == "master" ]] <<: *when_publish check-release: stage: prepare script: - ./nix/frama-c-public/check-release.sh <<: *when_release # Observed: when several shell with same dependencies are started, deadlock may # occur when building these dependencies. We build these dependencies # before running the rest of the pipeline to avoid that. prepare-shell-checkers: stage: prepare script: - ./nix/shell-checkers.sh "true" prepare-wp-cache: stage: prepare script: - ./nix/wp-cache.nix.sh artifacts: paths: - ./nix/wp-cache.nix ################################################################################ ### BUILD frama-c: stage: build script: - ./nix/build-proxy.sh frama-c artifacts: when: on_failure paths: - commits.nix - results.log expire_in: 1 day ivette: stage: build <<: *ivette_setup script: - make -C ivette dist tags: - docker ################################################################################ ### TESTS .build_template: &coverage_artifacts artifacts: name: coverage-$CI_JOB_NAME paths: - _bisect/*.tar.xz expire_in: 24h .build_template: &coverage variables: OUT: "_bisect" <<: *coverage_artifacts e-acsl-tests: stage: tests script: - ./nix/build-proxy.sh e-acsl-tests <<: *coverage .build_template: &eva_template stage: tests script: - ./nix/build-proxy.sh eva-$CONFIG-tests <<: *coverage_artifacts # Do not add OUT here, the parallel rule in Eva domains overload variables eva-default-tests: variables: CONFIG: "default" OUT: "_bisect" <<: *eva_template .build_template: &eva_domains parallel: matrix: - OUT: "_bisect" CONFIG: [ "apron", "bitwise", "equality", "gauges", "multidim", "octagon", "symblocs" ] eva-domains: <<: *eva_template <<: *eva_domains kernel-tests: stage: tests script: - ./nix/build-proxy.sh kernel-tests <<: *coverage plugins-tests: stage: tests script: - ./nix/build-proxy.sh plugins-tests <<: *coverage wp-tests: stage: tests script: - ./nix/build-proxy.sh wp-tests <<: *coverage ivette-tests: stage: tests when: manual <<: *ivette_setup script: - make -C ivette dist - cd ivette - xvfb-run --auto-servernum -e /dev/stdout -s "-screen 0 1920x1080x24 -ac -nolisten tcp -nolisten unix" dune exec -- yarn playwright test --headed artifacts: paths: - ivette/tests/test-results - ivette/screenshots when: always expire_in: 1 day tags: - docker external-plugins: stage: tests script: - ./nix/external-plugin-ci.sh $PLUGIN parallel: matrix: - PLUGIN: [ "acsl-importer", "caveat-importer", "context-from-precondition", "frama-clang", "genassigns", "meta", "minimal", "mthread", "pathcrawler", "security", "volatile" ] ################################################################################ ### DISTRIB # API documentation api-doc: stage: distrib variables: OUT: "api" script: - ./nix/build-proxy.sh api-doc artifacts: paths: - api/frama-c-api.tar.gz - api/frama-c-server-api.tar.gz expire_in: 7 days api-json-doc: stage: distrib variables: OUT: "api" script: - ./nix/build-proxy.sh api-json-doc artifacts: paths: - api/frama-c-api-json.tar.gz expire_in: 7 days # Build distribution tarball build-distrib-tarball: stage: distrib variables: OPEN_SOURCE: "yes" CI_LINK: "yes" HDRCK: "frama-c-hdrck" script: - ./nix/shell-checkers.sh "./dev/make-distrib.sh" artifacts: paths: - ./*.tar.gz expire_in: 1 week # Build ivette apps build-ivette-linux-packages: stage: distrib <<: *ivette_setup script: - make -C ivette dist-linux - mv ivette/dist/Ivette-arm64.AppImage ./frama-c-ivette-linux-ARM64.AppImage - mv ivette/dist/Ivette-x86_64.AppImage ./frama-c-ivette-linux-x86-64.AppImage artifacts: paths: - ./*.AppImage tags: - docker <<: *when_release build-ivette-macos-packages: stage: distrib script: # TS - export NVM_DIR="$HOME/.nvm" - . "$NVM_DIR/nvm.sh" - nvm install $NODE - nvm use $NODE # Opam - opam switch create --empty . - eval $(opam env --switch=. --set-switch) - opam pin . -n -k path - opam install headache - opam install --jobs 2 --deps-only . # Build Frama-C API - dune build -j2 @install - make -C ivette api # Build Ivette - make -C ivette dist-macOS - mv ivette/dist/Ivette-universal.dmg ./frama-c-ivette-macos-universal.dmg artifacts: paths: - ./*.dmg tags: - macos-arm <<: *when_release # Coverage coverage: stage: distrib variables: BISECT_DIR: "_bisect" script: - ./nix/shell-checkers.sh "./nix/coverage.sh" coverage: '/Coverage: \d+\.\d+\%/' artifacts: reports: coverage_report: coverage_format: cobertura path: report.xml expire_in: 1 week # Check files header header-check: stage: distrib script: - ./nix/shell-checkers.sh "make -f share/Makefile.headers check-headers" # Lint files lint: stage: distrib script: - ./nix/shell-checkers.sh "make -f share/Makefile.linting check-lint LINTCK_EXTRA=-s" # Manuals .build_template: &manuals_build_template stage: distrib variables: OUT: "manuals" script: - ./nix/build-proxy.sh manuals .build_template: &manuals_artifacts_template artifacts: paths: - manuals/*.pdf - manuals/*.tar.gz - manuals/*.txt expire_in: 7 days # Note: the LAST artifact of the ref is always kept manuals: <<: *manuals_build_template manuals-artifacts: <<: *manuals_build_template <<: *manuals_artifacts_template <<: *manual_when_not_special_pipeline manuals-nightly: <<: *manuals_build_template <<: *manuals_artifacts_template <<: *when_publish manuals-for-release: <<: *manuals_build_template <<: *manuals_artifacts_template <<: *when_release # Release artifacts release-content: stage: distrib script: - ./nix/shell-checkers.sh "./dev/build-release.sh" needs: - api-doc - build-distrib-tarball - build-ivette-linux-packages - build-ivette-macos-packages - manuals-for-release artifacts: paths: - website - wiki - opam-repository - release-data.json <<: *when_release ################################################################################ ### COMPATIBILITY # Internalized plugins tests .build_template: &internal_template stage: compatibility script: - ./nix/internal-tests.sh internal: <<: *internal_template when: manual except: - schedules internal-nightly: <<: *internal_template # The Opam target may affect this job timeout: 2h only: - schedules # Linux ARM & MacOS .build_template: &additional_arch_template stage: compatibility script: - opam update - opam switch create --empty . - eval $(opam env --switch=. --set-switch) # Note: we use this to get an exact version corresponding to a minor version - opam pin add ocaml $(grep $OCAML nix/ocaml-versions.txt) -n - opam install . --deps-only --with-test -y - dune build --display short --error-reporting=twice @install - dune exec -- frama-c-ptests tests src/plugins/*/tests - dune build --display short @ptests_config timeout: 2h tags: - ${ARCH} additional-arch: <<: *additional_arch_template <<: *manual_when_not_special_pipeline parallel: matrix: - ARCH: [linux-arm, macos-x86, macos-arm] additional-arch-nightly: <<: *additional_arch_template <<: *when_publish parallel: matrix: - ARCH: [linux-arm, macos-x86, macos-arm] additional-arch-release: <<: *additional_arch_template <<: *when_release parallel: matrix: - ARCH: [linux-arm, macos-x86, macos-arm] # OCaml versions .build_template: &ocaml_always_additional_versions_template parallel: matrix: - OCAML: ["5.2"] # Uncomment this block when there are intermediate versions to check manully .build_template: &ocaml_manual_additional_versions_template parallel: matrix: - OCAML: ["5.1"] when: manual .build_template: &ocaml_versions_template stage: compatibility script: - ./nix/build-proxy.sh default-config-tests ocaml-versions: <<: *ocaml_versions_template <<: *ocaml_always_additional_versions_template # in schedules, each OCAML is tested in its own complete pipeline except: - schedules # Uncomment this section when there are additional versions of OCaml to test ocaml-versions-more: <<: *ocaml_versions_template <<: *ocaml_manual_additional_versions_template ocaml-versions-nightly: <<: *ocaml_versions_template <<: *ocaml_always_additional_versions_template # in publish schedule, we still check additional versions of OCaml <<: *when_publish # Opam pin .build_template: &opam_pin_template stage: compatibility image: 'ocaml/opam:ubuntu-20.04-ocaml-$OCAML' script: - sudo apt update - opam pin . -n -k path - opam depext frama-c --with-test - opam install --jobs 2 frama-c --with-test --with-doc - frama-c --plugins tags: - docker opam-pin: <<: *opam_pin_template <<: *manual_when_not_special_pipeline opam-pin-nightly: <<: *opam_pin_template <<: *when_schedules opam-pin-release: <<: *opam_pin_template <<: *when_release .build_template: &opam_pin_minimal_template stage: compatibility image: 'ocaml/opam:ubuntu-20.04-ocaml-$OCAML' variables: OPAMDOWNLOADJOBS: "1" OPAMERRLOGLEN: "0" OPAMSOLVERTIMEOUT: "500" OPAMPRECISETRACKING: "1" script: - sudo ln -f /usr/bin/opam-2.1 /usr/bin/opam - opam --version - opam init --reinit -ni - sudo apt update - export OPAMCRITERIA="-removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed" - export OPAMFIXUPCRITERIA="-removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed" - export OPAMUPGRADECRITERIA="-removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed" - opam pin . -n -k path - opam update --depexts - opam depext --jobs 2 frama-c - export OPAMCRITERIA="+removed,+count[version-lag,solution]" - export OPAMFIXUPCRITERIA="+removed,+count[version-lag,solution]" - export OPAMUPGRADECRITERIA="+removed,+count[version-lag,solution]" - export OPAMEXTERNALSOLVER="builtin-0install" - opam update --depexts - opam reinstall --jobs 2 frama-c - frama-c --plugins timeout: 2h tags: - docker opam-pin-minimal: <<: *opam_pin_minimal_template <<: *manual_when_not_special_pipeline opam-pin-minimal-nightly: <<: *opam_pin_minimal_template <<: *when_schedules opam-pin-minimal-release: <<: *opam_pin_minimal_template <<: *when_release # Distrib .build_template: &src_distrib_tests_template stage: compatibility variables: DIR: "extracted" script: - mkdir $DIR && tar -xzf frama-c.tar.gz --strip-components 1 -C ./extracted - ./nix/build-proxy.sh src-distrib-tests # The Opam target may affect this job timeout: 2h src-distrib-tests: <<: *src_distrib_tests_template <<: *manual_when_not_special_pipeline src-distrib-tests-scheduled: <<: *src_distrib_tests_template <<: *when_schedules src-distrib-tests-release: <<: *src_distrib_tests_template <<: *when_release ################################################################################ ### RELEASE .build_template: &prepare_ssh_template before_script: - export GIT_SSH=$PWD/nix/frama-c-public/ssh.sh release-branch: stage: release variables: REPOSITORY: "frama-c" <<: *prepare_ssh_template script: - (! git merge-base --is-ancestor a1e186c68a6418a53b3dc06237f49e8dcbf75f4a origin/$CI_COMMIT_BRANCH) - BRANCH="$CI_COMMIT_BRANCH" nix-shell -p coreutils openssh --run './nix/frama-c-public/publish-branch.sh' # Note: BRANCH must be defined here, since we cannot *evaluate* a variable in 'variables' <<: *when_release when: manual interruptible: false release-create: stage: release <<: *prepare_ssh_template script: - nix-shell -p git git-lfs coreutils openssh curl --run './nix/frama-c-public/publish-release.sh' needs: - release-branch - release-content <<: *when_release when: manual interruptible: false release-opam: stage: release <<: *prepare_ssh_template script: - nix-shell -p git git-lfs coreutils openssh --run './nix/frama-c-public/publish-opam.sh' <<: *when_release interruptible: false release-website: stage: release <<: *prepare_ssh_template script: - nix-shell -p git git-lfs coreutils openssh --run './nix/frama-c-public/publish-website.sh' <<: *when_release interruptible: false release-wiki: stage: release <<: *prepare_ssh_template script: - nix-shell -p git git-lfs coreutils openssh --run './nix/frama-c-public/publish-wiki.sh' <<: *when_release interruptible: false ################################################################################ ### PUBLISH # publish stage is used to push the current master branch of Frama-C and # associated plugins from the internal frama-c group to the public pub group. # # For that, it uses the 'frama-c to frama-c-public' publish key. Thus, to publish # a new plugin (while keeping its main repository internal), you can add a new # target to this stage, adapting the script for MetAcsl or Frama-Clang to your # own plugin. # # You must also activate the publish key on both frama-c/my_plugin # and pub/my_plugin repositories (the former should be read-only, the latter # must provide write access to the publish key). # Do not forget to trigger the target only on schedules, so that all public # repositories stay synchronized. publish-frama-c: stage: publish variables: BRANCH: "master" REPOSITORY: "frama-c" <<: *prepare_ssh_template script: - (! git merge-base --is-ancestor a1e186c68a6418a53b3dc06237f49e8dcbf75f4a origin/master) - nix-shell -p coreutils openssh --run './nix/frama-c-public/publish-branch.sh' <<: *when_publish interruptible: false publish-fclang: stage: publish variables: BRANCH: "master" REPOSITORY: "frama-clang" <<: *prepare_ssh_template script: - nix-shell -p coreutils openssh --run './nix/frama-c-public/publish-branch.sh' <<: *when_publish interruptible: false publish-meta: stage: publish variables: BRANCH: "master" REPOSITORY: "meta" <<: *prepare_ssh_template script: - nix-shell -p coreutils openssh --run './nix/frama-c-public/publish-branch.sh' <<: *when_publish interruptible: false publish-frama-c-api: stage: publish <<: *prepare_ssh_template script: - nix-shell -p coreutils openssh --run './nix/frama-c-public/publish-api.sh' only: variables: - $PUBLISH == "yes" interruptible: false