{"id":14966302,"url":"https://github.com/rocq-community/docker-coq-action","last_synced_at":"2025-10-25T16:30:51.097Z","repository":{"id":41048346,"uuid":"250054135","full_name":"coq-community/docker-coq-action","owner":"coq-community","description":"GitHub Action using Docker-Coq [maintainers=@erikmd,@Zimmi48]","archived":false,"fork":false,"pushed_at":"2025-02-09T20:53:46.000Z","size":310,"stargazers_count":12,"open_issues_count":23,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-09T21:29:33.035Z","etag":null,"topics":["action","container-ci","continuous-integration","coq","docker-coq","docker-coq-action","github-actions","opam"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coq-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-25T18:07:29.000Z","updated_at":"2025-02-09T20:53:50.000Z","dependencies_parsed_at":"2024-05-12T14:26:14.112Z","dependency_job_id":"65cd646e-e3d0-4cc9-a630-b5fe27bd9907","html_url":"https://github.com/coq-community/docker-coq-action","commit_stats":{"total_commits":140,"total_committers":8,"mean_commits":17.5,"dds":"0.15714285714285714","last_synced_commit":"ae62702328d3d202def6f57883b6ad788fbdae8f"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":"actions/container-action","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coq-community%2Fdocker-coq-action","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coq-community%2Fdocker-coq-action/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coq-community%2Fdocker-coq-action/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coq-community%2Fdocker-coq-action/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coq-community","download_url":"https://codeload.github.com/coq-community/docker-coq-action/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238024406,"owners_count":19403837,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["action","container-ci","continuous-integration","coq","docker-coq","docker-coq-action","github-actions","opam"],"created_at":"2024-09-24T13:36:11.395Z","updated_at":"2025-10-25T16:30:50.445Z","avatar_url":"https://github.com/coq-community.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Docker-Coq GitHub Action\n\n[![reviewdog][reviewdog-badge]][reviewdog-link]\n[![Docker-Coq CI][docker-coq-ci-badge]][docker-coq-ci-link]\n[![Docker-based CI][python-ci-badge]][python-ci-link]\n[![Regression Test][rt-ci-badge]][rt-ci-link]  \n[![coqorg][coqorg-shield]][coqorg-link]\n[![mathcomp][mathcomp-shield]][mathcomp-link]\n[![Example][example-shield]][example-link]\n[![Contributing][contributing-shield]][contributing-link]\n[![Code of Conduct][conduct-shield]][conduct-link]\n\n[reviewdog-badge]: https://github.com/coq-community/docker-coq-action/actions/workflows/reviewdog.yml/badge.svg?branch=master\n[docker-coq-ci-badge]: https://github.com/coq-community/docker-coq-action/actions/workflows/coq-demo.yml/badge.svg?branch=master\n[python-ci-badge]: https://github.com/coq-community/docker-coq-action/actions/workflows/python-demo.yml/badge.svg?branch=master\n[rt-ci-badge]: https://github.com/coq-community/docker-coq-action/actions/workflows/gha-rt.yml/badge.svg?branch=master\n[reviewdog-link]:https://github.com/coq-community/docker-coq-action/actions/workflows/reviewdog.yml\n[docker-coq-ci-link]:https://github.com/coq-community/docker-coq-action/actions/workflows/coq-demo.yml\n[python-ci-link]:https://github.com/coq-community/docker-coq-action/actions/workflows/python-demo.yml\n[rt-ci-link]:https://github.com/coq-community/docker-coq-action/actions/workflows/gha-rt.yml\n\n[coqorg-shield]: https://img.shields.io/badge/depends%20on-coqorg%2Fcoq-blue.svg\n[coqorg-link]: https://hub.docker.com/r/coqorg/coq\n\n[mathcomp-shield]: https://img.shields.io/badge/see%20also-mathcomp%2Fmathcomp-blue.svg\n[mathcomp-link]: https://hub.docker.com/r/mathcomp/mathcomp\n\n[example-shield]: https://img.shields.io/badge/see%20also-example-brightgreen.svg\n[example-link]: https://github.com/erikmd/docker-coq-github-action-demo\n\n[contributing-shield]: https://img.shields.io/badge/contributions-welcome-%23f7931e.svg\n[contributing-link]: https://github.com/coq-community/manifesto/blob/master/CONTRIBUTING.md\n\n[conduct-shield]: https://img.shields.io/badge/%E2%9D%A4-code%20of%20conduct-%23f15a24.svg\n[conduct-link]: https://github.com/coq-community/manifesto/blob/master/CODE_OF_CONDUCT.md\n\nThis is a GitHub Action that uses (by default)\n[rocq/rocq-prover](https://hub.docker.com/r/rocq/rocq-prover/) Docker images\n(for Rocq ≥ 9.0) and\n[coqorg/coq](https://hub.docker.com/r/coqorg/coq/) Docker images\n(for Coq ≤ 8.20.1),\nwhich in turn are based on [rocq/base](https://hub.docker.com/r/rocq/base/),\na Docker image with a Debian environment.\n\n|   | GitHub repo                                                             | Type          | Docker Hub                                                       |\n|---|-------------------------------------------------------------------------|---------------|------------------------------------------------------------------|\n| ⊙ | [docker-coq-action](https://github.com/coq-community/docker-coq-action) | GitHub Action | N/A                                                              |\n| ↳ | [docker-rocq](https://github.com/coq-community/docker-rocq)             | Dockerfile    | [`rocq/rocq-prover`](https://hub.docker.com/r/rocq/rocq-prover/) |\n| ↳ | [docker-base](https://github.com/coq-community/docker-base)             | Dockerfile    | [`rocq/base`](https://hub.docker.com/r/rocq/base/)               |\n| ↳ | Debian                                                                  | Linux distro  | [`debian`](https://hub.docker.com/_/debian/)                     |\n\nFor more details about these images, see the\n[docker-coq wiki](https://github.com/coq-community/docker-coq/wiki).\n\n## OPAM\n\nThe `docker-coq-action` provides built-in support for `opam` builds.\n\n`coq` is built on-top of `ocaml` and so `coq` projects use `ocaml`'s\npackage manager (`opam`) to build themselves.\nThis GitHub Action supports `opam` out of the box.\nIf your project does not already have a `coq-….opam` file, you might\ngenerate one such file by using the corresponding template gathered in\n[coq-community/templates](https://github.com/coq-community/templates#readme).\n\nThis `.opam` file can then serve as a basis for submitting releases in\n[coq/opam-coq-archive](https://github.com/coq/opam-coq-archive), and\nrelated guidelines (including the required **`.opam` metadata**) are\navailable in \u003chttps://coq.inria.fr/opam-packaging.html\u003e.\n\nMore details can be found in the\n[opam documentation](https://opam.ocaml.org/doc/Packaging.html#The-file-format-in-more-detail).\n\nAssuming the Git repository contains a `folder/coq-proj.opam` file,\nit will run (by default) the following commands:\n\n```bash\nopam config list; opam repo list; opam list\nsudo apt-get update -y -q\nopam pin add -n -y -k path coq-proj folder\nopam update -y\nopam install --confirm-level=unsafe-yes -j 2 coq-proj --deps-only\nopam list\nopam install -y -v -j 2 coq-proj\nopam list\nopam remove -y coq-proj\n```\n\nThe `apt-get` command and the `--confirm-level=unsafe-yes` opam option\nare necessary for automatic installation of system packages\nthat may be required by `coq-proj.opam`, as described in the\n[opam 2.1 release notes](https://opam.ocaml.org/blog/opam-2-1-0/#Seamless-integration-of-System-dependencies-handling-a-k-a-quot-depexts-quot).\n\n## Using the GitHub Action\n\nUsing a [GitHub Action](https://docs.github.com/en/actions)\nin your GitHub repository amounts to committing a file `.github/workflows/your-workflow-name.yml`,\ne.g. `.github/workflows/build.yml`, containing (among others), a snippet such as:\n\n```yaml\nruns-on: ubuntu-latest  # container actions require GNU/Linux\nstrategy:\n  matrix:\n    coq_version:\n      - '8.16'\n      - dev\n    ocaml_version: ['default']\n  fail-fast: false  # don't stop jobs if one fails\nsteps:\n  - uses: actions/checkout@v3\n  - uses: coq-community/docker-coq-action@v1\n    with:\n      opam_file: 'folder/coq-proj.opam'\n      coq_version: ${{ matrix.coq_version }}\n      ocaml_version: ${{ matrix.ocaml_version }}\n```\n\nEach field can be customized, see below\nfor the documentation of those specific to the docker-coq-action,\nor the GitHub Actions official documentation for the\n[standard fields involved in workflows](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions).\n\n### References\n\nFor details, see also:\n\n* the [action.yml](./action.yml) file (containing the metadata processed by the GitHub Actions platform itself, as well as some comments, albeit more terse than the [documentation below](#inputs));\n* the accompanying [`coq-demo` example repo](https://github.com/erikmd/docker-coq-github-action-demo);\n* the two workflows [coq-demo.yml](./.github/workflows/coq-demo.yml) and [python-demo.yml](./.github/workflows/python-demo.yml) that both serve as `docker-coq-action`'s CI test-suite and provide some examples of use.\n\n### Versioning\n\nThe Git repo of `docker-coq-action` uses `master` as developing branch\nand `v1` as release branch; and the corresponding tags `v1.x.y` follow\n[semantic versioning](https://semver.org/).\n\nWe develop `docker-coq-action` with a special focus on backward\ncompatibility, so that if your workflow just uses\n**`coq-community/docker-coq-action@v1`**, you will be able to benefit\nfrom new features, while expecting no breaking change.\n\nHowever, we recall that the version of any GitHub Action can just as\nwell be [referenced by a tag or a commit SHA](https://docs.github.com/en/actions/learn-github-actions/finding-and-customizing-actions#using-release-management-for-your-custom-actions).\n\nContrary to some custom practice of GitHub Actions maintainers, we do not change to which commit a tag points once it is published.\nAs a result, the latest stable version denoted by the short Git reference `v1` is implemented as a *release branch*, not as a tag.\nAnyway, if you do not trust the maintainers of a given GitHub Action, it is always safer to reference a *commit SHA*.\n\n### Inputs\n\n#### `opam_file`\n\n*Optional*\n\nThe path of the `.opam` file (or a directory), relative to the repo root.\n\nDefault: `\".\"` (if the argument is omitted or an empty string).\n\n*Note-1:* relying on the value of this `INPUT_OPAM_FILE` variable, the\nfollowing two variables are exported when running the `custom_script`:\n\n```bash\nif [ -z \"$INPUT_OPAM_FILE\" ] || [ -d \"$INPUT_OPAM_FILE\" ]; then\n    WORKDIR=\"\"\n    PACKAGE=${INPUT_OPAM_FILE:-.}\nelse\n    WORKDIR=$(dirname \"$INPUT_OPAM_FILE\")\n    PACKAGE=$(basename \"$INPUT_OPAM_FILE\" .opam)\nfi\n```\n\n*Note-2:* if this value is a directory (e.g., `.`), relying on the\n[`custom_script` default value](#custom_script), the action will\ninstall all the `*.opam` packages stored in this directory.\n\n#### `coq_version`\n\n*Optional*\n\nThe version of Coq. E.g., `\"8.10\"`.\n\nDefault: `\"latest\"` (= latest stable version).\n\nAppend the `-native` suffix if the version is `\u003e= 8.13` (or `dev`)\n*and* you are interested in the image that contains the\n[`coq-native`](https://opam.ocaml.org/packages/coq-native/) package.\nE.g., `\"8.13-native\"`, `\"latest-native\"`, `\"dev-native\"`.\n\nIf the `coq_version` value contains the `-native` suffix,\nthe `ocaml_version` value is ignored (as `coq-native` images only come with a single OCaml version).\nStill, a warning is raised if `ocaml_version` is nonempty and different from `\"default\"`.\n\n#### `ocaml_version`\n\n*Optional*\n\nThe version of OCaml.\n\nDefault: `\"default\"` (= Docker-Coq's default OCaml version for the given Coq version).\n\nAmong `\"default\"`, `\"4.02\"`, `\"4.05\"`, `\"4.07-flambda\"`, `\"4.08-flambda\"`, `\"4.09-flambda\"`, `\"4.10-flambda\"`, `\"4.11-flambda\"`, `\"4.12-flambda\"`, `\"4.13-flambda\"`, `\"4.14-flambda\"`…\n\n**Warning!** not all OCaml versions are available with all Coq versions.\n\nThe supported compilers w.r.t. each version of Coq are documented in the\n[OCaml-versions policy](https://github.com/coq-community/docker-coq/wiki#ocaml-versions-policy) section of the `docker-coq` wiki.\n\n#### `before_install`\n\n*Optional*\n\nThe bash snippet to run before `install`\n\nDefault:\n\n```bash\nstartGroup \"Print opam config\"\n  opam config list; opam repo list; opam list\nendGroup\n```\n\nSee [`custom_script`](#custom_script) and [startGroup/endGroup](#startGroupendGroup) for more details.\n\n#### `install`\n\n*Optional*\n\nThe bash snippet to install the `opam` `PACKAGE` dependencies.\n\nDefault:\n\n```bash\nstartGroup \"Install dependencies\"\n  sudo apt-get update -y -q\n  opam pin add -n -y -k path $PACKAGE $WORKDIR\n  opam update -y\n  opam install --confirm-level=unsafe-yes -j 2 $PACKAGE --deps-only\nendGroup\n```\n\nwhere `$PACKAGE` and `$WORKDIR` are set from the [`opam_file`](#opam_file) variable.\n\nSee [`custom_script`](#custom_script) and [startGroup/endGroup](#startGroupendGroup) for more details.\n\n#### `after_install`\n\n*Optional*\n\nThe bash snippet to run after `install` (if successful).\n\nDefault:\n\n```bash\nstartGroup \"List installed packages\"\n  opam list\nendGroup\n```\n\nSee [`custom_script`](#custom_script) and [startGroup/endGroup](#startGroupendGroup) for more details.\n\n#### `before_script`\n\n*Optional*\n\nThe bash snippet to run before `script`.\n\nDefault: `\"\"` (empty string).\n\nSee [`custom_script`](#custom_script) and [startGroup/endGroup](#startGroupendGroup) for more details.\n\n#### `script`\n\n*Optional*\n\nThe bash snippet to install the `opam` `PACKAGE`.\n\nDefault:\n\n```bash\nstartGroup \"Build\"\n  opam install -y -v -j 2 $PACKAGE\n  opam list\nendGroup\n```\n\nwhere `$PACKAGE` is set from the [`opam_file`](#opam_file) variable.\n\nSee [`custom_script`](#custom_script) and [startGroup/endGroup](#startGroupendGroup) for more details.\n\n#### `after_script`\n\n*Optional*\n\nThe bash snippet to run after `script` (if successful).\n\nDefault: `\"\"` (empty string).\n\nSee [`custom_script`](#custom_script) and [startGroup/endGroup](#startGroupendGroup) for more details.\n\n#### `uninstall`\n\n*Optional*\n\nThe bash snippet to uninstall the `opam` `PACKAGE`.\n\nDefault:\n\n```bash\nstartGroup \"Uninstallation test\"\n  opam remove -y $PACKAGE\nendGroup\n```\n\nwhere `$PACKAGE` is set from the [`opam_file`](#opam_file) variable.\n\nSee [`custom_script`](#custom_script) and [startGroup/endGroup](#startGroupendGroup) for more details.\n\n#### `custom_script`\n\n*Optional*\n\nThe main script run in the container; may be overridden; but overriding more specific parts of the script is preferred.\n\nDefault:\n\n```\n{{before_install}}\n{{install}}\n{{after_install}}\n{{before_script}}\n{{script}}\n{{after_script}}\n{{uninstall}}\n```\n\n*Note-1:* the semantics of this variable is a *standard Bash script*,\nthat is evaluated within the workflow container after replacing the\n\"mustache\" placeholders with the value of their variable counterpart.\nFor example, `{{uninstall}}` will be replaced with the value of the\n[`uninstall`](#uninstall) variable (the default value of which being\nthe string `opam remove -y $PACKAGE`).\n\n*Note-2:* this option is named `custom_script` rather than `run` or so\nto **discourage changing its recommended, default value** for building\na regular `opam` project, while keeping the flexibility to be able to\nchange it.\n\n*Note-3:* if you decide to override the `custom_script` value anyway,\nyou can just as well rely on the \"mustache interpolation\" of\n`{{before_install}}` … `{{uninstall}}`, and customize the underlying\nvalues.\n\n#### `custom_image`\n\n*Optional*\n\nThe name of the Docker image to pull.\n\nDefault: unset\n\nIf this variable is unset, its value is computed from the values of\nkeywords `coq_version` and `ocaml_version`.\n\nIf you use the standard\n[`docker-rocq`](https://github.com/coq-community/docker-rocq) images, we\nrecommend to directly use keywords `coq_version` and `ocaml_version`.\n\nIf you use another registry such as that of\n[`docker-mathcomp`](https://github.com/math-comp/docker-mathcomp)\nimages, you can benefit from that keyword by writing a configuration\nsuch as:\n\n```yaml\nruns-on: ubuntu-latest\nstrategy:\n  matrix:\n    image:\n      - mathcomp/mathcomp:1.10.0-coq-8.10\n      - mathcomp/mathcomp:1.10.0-coq-8.11\n      - mathcomp/mathcomp:1.11.0-coq-dev\n      - mathcomp/mathcomp-dev:coq-dev\n  fail-fast: false  # don't stop jobs if one fails\nsteps:\n  - uses: actions/checkout@v4\n  - uses: coq-community/docker-coq-action@v1\n    with:\n      opam_file: 'folder/coq-proj.opam'\n      custom_image: ${{ matrix.image }}\n```\n\nIf ever you want to retrieve the Docker image name within the CI script, you can \nuse the [`export`](#export) keyword to expose the `COQ_IMAGE` internal variable.\n\n#### `export`\n\n*Optional*\n\nA space-separated list of `env` variables to export to the `custom_script`.\n\nDefault: `\"\"`, i.e., no additional variable is exported.\n\n*Note-1:* The values of the variables to export may be defined by using the\n[`env`](https://docs.github.com/en/actions/reference/environment-variables)\nkeyword.\n\n*Note-2:* Regarding the naming of these variables:\n\n* Only use ASCII letters, `_` and digits, i.e., matching the `[a-zA-Z_][a-zA-Z0-9_]*` regexp.\n* Avoid [reserved identifiers](https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables) (namely: `HOME`, `CI`, and strings starting with `GITHUB_`, `ACTIONS_`, `RUNNER_`, or `INPUT_`).\n* The `docker-coq-action` internally sets a `COQ_IMAGE` environment variable that contains the full name of the Docker image used. Use `export: 'COQ_IMAGE'` to make this variable available within the [script](#custom_script).\n\nHere is a minimal working example of this feature:\n\n```yaml\nruns-on: ubuntu-latest\nsteps:\n  - uses: actions/checkout@v4\n  - uses: coq-community/docker-coq-action@v1\n    with:\n      opam_file: 'folder/coq-proj.opam'\n      coq_version: 'dev'\n      ocaml_version: 'default'\n      export: 'OPAMWITHTEST'  # space-separated list of variables\n    env:\n      OPAMWITHTEST: 'true'\n```\n\nHere, setting the [`OPAMWITHTEST`](https://opam.ocaml.org/doc/man/opam-install.html#lbAG)\nenvironment variable is useful to run the unit tests\n(specified using `opam`'s [`with-test`](https://opam.ocaml.org/doc/Manual.html#pkgvar-with-test)\nclause) after the package build.\n\n## Remarks\n\n### startGroup/endGroup\n\nThe default value of fields `{{before_install}}`, `{{install}}`,\n`{{after_install}}`, `{{script}}`, and `{{uninstall}}` involves the bash\nfunctions `startGroup` (taking 1 argument: `startGroup \"Group title\"`)\nand `endGroup`.\n\nThese bash functions are defined in [timegroup.sh](./timegroup.sh) and have the following features:\n\n* they create foldable groups in the GitHub Actions logs\n    (see the [online doc](https://github.com/actions/toolkit/blob/master/docs/commands.md#group-and-ungroup-log-lines)),\n* and they compute the elapsed time for the considered group;\n* these groups cannot be nested,\n* and if an `endGroup` has been forgotten, it is implicitly and\n  automatically inserted at the next `startGroup` (albeit it is better\n  to make each `endGroup` explicit, for readability).\n\nHere is an example of script along with the output log so obtained:\n\n```bash\nex_var=\"ex_value\"\n# […]\n\nstartGroup \"Toy example\"\n  echo \"ex_var=$ex_var\"\nendGroup\n```\n\n* Folded version:\n\n  [![folded group](./images/2021-08-11_ex_log_folded.png)](./images/2021-08-11_ex_log_folded.png)\n\n* Unfolded version:\n\n  [![unfolded group](./images/2021-08-11_ex_log_unfolded.png)](./images/2021-08-11_ex_log_unfolded.png)\n\n### Pitfall: do not use `\u0026\u0026`; use semicolons\n\nBeware that the following script is *buggy*:\n\n```yaml\nscript: |\n  startGroup \"Build project\"\n    make -j2 \u0026\u0026 make test \u0026\u0026 make install\n  endGroup\n```\n\nBecause if `make test` fails, it won't make the CI fail.\n\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e(Explanation)\u003c/b\u003e\u003c/summary\u003e\n\nThis is a typical pitfall that occur *in any shell-based CI platform*\nwhere the [`set -e`](\nhttps://manpages.ubuntu.com/manpages/hirsute/en/man1/set.1posix.html#description)\noption is implied: the early-exit associated to this option is\ndisabled if the failing command is followed by `\u0026\u0026` or `||`.\n\nSee e.g., the output of the following three commands:\n\n```bash\nbash -c 'set -e; false \u0026\u0026 true; echo $?; echo this should not be run'\n# → 1\n# → this should not be run\n\nbash -c 'set -e; false; true; echo $?; echo this should not be run'\n# (no output)\n\nbash -c 'set -e; ( false \u0026\u0026 true ); echo $?; echo this should not be run'\n# (no output)\n```\n\n\u003c/details\u003e\n\nInstead, you should write one of the following variants:\n\n* using semicolons:\n\n  ```yaml\n  script: |\n    startGroup \"Build project\"\n      make -j2 ; make test ; make install\n    endGroup\n  ```\n\n* using newlines:\n\n  ```yaml\n  script: |\n    startGroup \"Build project\"\n      make -j2\n      make test\n      make install\n    endGroup\n  ```\n\n* using `\u0026\u0026` but within a subshell:\n\n  ```yaml\n  script: |\n    startGroup \"Build project\"\n      ( make -j2 \u0026\u0026 make test \u0026\u0026 make install )\n    endGroup\n  ```\n\n### Permissions\n\nIf you use the\n[`docker-rocq`](https://github.com/coq-community/docker-rocq) images,\nthe container user has UID=GID=1000 while the GitHub Actions workdir\nhas (UID=1001, GID=116).\nThis is not an issue when relying on `opam` to build the Coq project.\nOtherwise, you may want to use `sudo` in the container to change the\npermissions. You may also install additional Debian packages\n(see the [dedicated section below](#install-debian-packages)).\n\nTypically, this would lead to a workflow specification like this:\n\n```yaml\nruns-on: ubuntu-latest\nstrategy:\n  matrix:\n    image:\n      - 'rocq/rocq-prover:dev'\n  fail-fast: false  # don't stop jobs if one fails\nsteps:\n  - uses: actions/checkout@v4\n  - uses: coq-community/docker-coq-action@v1\n    with:\n      opam_file: 'folder/coq-proj.opam'\n      custom_image: ${{ matrix.image }}\n      before_script: |\n        startGroup \"Workaround permission issue\"\n          sudo chown -R 1000:1000 .  # \u003c--\n        endGroup\n      script: |\n        startGroup \"Build project\"\n          make -j2\n        endGroup\n      uninstall: |\n        startGroup \"Clean project\"\n          make clean\n        endGroup\n  - name: Revert permissions\n    # to avoid a warning at cleanup time\n    if: ${{ always() }}\n    run: sudo chown -R 1001:116 .  # \u003c--\n```\n\nFor more details, see the\n[CI setup / Remarks](https://github.com/coq-community/docker-coq/wiki/CI-setup#remarks)\nsection in the `docker-coq` wiki.\n\n### Artifacts\n\nThe `docker-coq-action` and its \"child\" Docker image (specified by the\n[`custom_image`](#custom_image) field) run inside a container, which\nimplies the associated filesystem is isolated from the runner.\n\nHowever, the GitHub workspace directory is made available in the\ncontainer (using a so-called bind-mount) and set as the current\nworking directory.\n\nAs a result:\n\n* all the files installed outside of this GitHub workspace directory\n  (such as `opam` packages installed in `/home/coq/.opam`) are \"lost\"\n  when `docker-coq-action` terminates;\n* all the files put in the GitHub workspace directory (or in a\n  sub-directory) are kept;  \n  so it is possible to create artifacts, then use an action such as\n  [`actions/upload-artifact@v4`](https://github.com/actions/upload-artifact)\n  in a subsequent step.\n\nHere is an example job for this use case, which also takes into\naccount the previously-mentioned [permissions workaround](#permissions):\n\n```yaml\nruns-on: ubuntu-latest\nstrategy:\n  matrix:\n    image:\n      - 'rocq/rocq-prover:dev'\n  fail-fast: false  # don't stop jobs if one fails\n    steps:\n      - uses: coq-community/docker-coq-action@v1\n        with:\n          opam_file: 'folder/coq-proj.opam'\n          custom_image: ${{ matrix.image }}\n          before_script: |\n            startGroup \"Workaround permission issue\"\n              sudo chown -R 1000:1000 .\n            endGroup\n          script: |\n            startGroup \"Build project\"\n              coq_makefile -f _CoqProject -o Makefile\n              make -j2\n            endGroup\n          after_script: |\n            set -o pipefail  # recommended if the script uses pipes\n\n            startGroup \"Build artifacts\"\n              mkdir -v -p artifacts\n              opam list \u003e artifacts/opam_list.txt\n              make test 2\u003e\u00261 | tee artifacts/make_test.txt\n            endGroup\n          uninstall: ''\n      - name: Revert permissions\n        # to avoid a warning at cleanup time\n        if: ${{ always() }}\n        run: sudo chown -R 1001:116 .\n      - uses: actions/upload-artifact@v4\n        with:\n          name: example-artifact\n          path: artifacts/\n          if-no-files-found: error  # 'warn' or 'ignore' are also available, defaults to `warn`\n          retention-days: 8\n```\n\n### GitHub Actions environment files\n\nRecall that `docker-coq-action` runs your CI script in a Docker container,\nthe filesystem of which being isolated from the GitHub runner.\n\nStill, `docker-coq-action` bind-mounts some special paths for\n[GitHub Actions environment files](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files),\nso that `\"$GITHUB_ENV\"`, `\"$GITHUB_OUTPUT\"`, and `\"$GITHUB_STEP_SUMMARY\"` can be used\nin (parts of) the [`custom_script`](#custom_script) in order to pass environment\nvariables or step outputs to the following steps, or set a Markdown summary.\n\nConversely, the [`export`](#export) keyword can be used to pass variables\nfrom the previous step to `docker-coq-action`.\n\nHere is an example of script that uses `GITHUB_ENV` and `GITHUB_OUTPUT`:\n\n\n```yaml\nruns-on: ubuntu-latest\nstrategy:\n  matrix:\n    image:\n      - 'rocq/rocq-prover:9.0'\n  fail-fast: false  # don't stop jobs if one fails\nsteps:\n  - uses: actions/checkout@v4\n  - uses: coq-community/docker-coq-action@v1\n    id: docker-coq-action  # needed to get step outputs\n    with:\n      opam_file: 'folder/coq-proj.opam'\n      custom_image: ${{ matrix.image }}\n      after_script: |\n        # Pass values to upcoming steps in two different ways\n        echo \"coq_version_var=$(opam var coq:version)\" \u003e\u003e \"$GITHUB_ENV\"\n        echo \"coq_version_out=$(opam var coq:version)\" \u003e\u003e \"$GITHUB_OUTPUT\"\n  - name: Next step\n    env:\n      coq_version_var2: ${{ steps.docker-coq-action.outputs.coq_version_out }}\n    run: |\n      : Summary\n      echo \"Previous step used: coq_version=$coq_version_var\"\n      echo \"Previous step used: coq_version=$coq_version_var2 (same)\"\n```\n\n### Install Debian packages\n\nIf you use `docker-coq-action` with a\n[docker-rocq](https://github.com/coq-community/docker-rocq) image (the\ndefault when the [`custom_image`](#custom_image) field is omitted),\nthe image is based on Debian stable and the container user\n(UID=GID=1000) has `sudo` rights, so you can rely on `apt-get` to\ninstall additional Debian packages.\n\nThis use case is illustrated by the following job that installs\nthe `emacs` and `tree` packages:\n\n```yaml\nruns-on: ubuntu-latest\nstrategy:\n  matrix:\n    image:\n      - 'rocq/rocq-prover:dev'\n  fail-fast: false  # don't stop jobs if one fails\nsteps:\n  - uses: actions/checkout@v4\n  - uses: coq-community/docker-coq-action@v1\n    with:\n      opam_file: 'folder/coq-proj.opam'\n      custom_image: ${{ matrix.image }}\n      before_script: |\n        startGroup \"Install APT dependencies\"\n          cat /etc/os-release  # Print the Debian OS version\n          # sudo apt-get update -y -q # this mandatory command is already run in install step by default\n          sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -q --no-install-recommends \\\n            emacs \\\n            tree  # for instance\n            # Alphabetical order is recommended for long package lists to ease review and update\n        endGroup\n      after_script: |\n        startGroup \"Post-test\"\n          emacs --version\n          tree\n        endGroup\n```\n\n### Verbose output and Variable leaking\n\nThe code run in the `docker-coq-action` container relies on the\nfollowing invocation to display a customized prompt before each\ncommand:\n\n```bash\nexport PS4='+ \\e[33;1m($0 @ line $LINENO) \\$\\e[0m '; set -ex\n```\n\nAs a result, due to the `set -x` option, the value of each variable is\nexposed in the log.\n\nFor example, the script:\n\n```bash\nstartGroup \"Risky example\"\n  TOKEN=$(uuidgen -r)\n  curl -fsS -X POST -F token=\"$TOKEN\" https://example.com \u003e/dev/null\nendGroup\n```\n\nwill produce a log such as:\n\n[![verbose log](./images/2021-08-11_too_verbose_log.png)](./images/2021-08-11_too_verbose_log.png)\n\nHence the following two remarks:\n\n1. If need be, it is possible to temporarily disable the trace feature\n   in your script, surrounding the lines at stake by (`set +x`, `set -x`).  \n   Your script would thus look like:\n\n   ```bash\n   set +x\n\n   #...some code with no trace...\n\n   set -x\n   ```\n\n   or, to get some even less verbose output:\n\n   ```bash\n   { set +x; } 2\u003e/dev/null\n\n   #...some code with no trace...\n\n   set -x\n   ```\n\n2. Fortunately, this trace feature cannot make repository secrets\n   `${{ secrets.STH }}` leak, as\n   [GitHub Actions automatically redact them in the log](https://docs.github.com/en/actions/reference/encrypted-secrets#accessing-your-secrets).  \n   Regarding secrets obtained by other means, e.g. from a command-line\n   program, it is recommended to perform the three actions below **in a\n   previous `run:` step**:\n\n   * store the \"locally-created secret\" in an environment variable:\n\n     ```bash\n     SOME_TOKEN=\"...\"\n     ```\n\n   * immediately [mark the variable as masked](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#masking-a-value-in-log):\n\n     ```bash\n     echo \"::add-mask::$SOME_TOKEN\"\n     ```\n\n   * register the variable to [make it available for subsequent steps](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable):\n\n     ```bash\n     printf \"%s\\n\" \"SOME_TOKEN=$(printf \"%q\" \"$SOME_TOKEN\")\" \u003e\u003e $GITHUB_ENV\n     ```\n\n   A comprehensive example of this approach is available in PR [erikmd/docker-coq-github-action-demo#12](https://github.com/erikmd/docker-coq-github-action-demo/pull/12).\n\n   For completeness, note that masking inputs involved in `workflow_dispatch` may require some `jq`-based workaround, as mentioned in issue [actions/runner#643](https://github.com/actions/runner/issues/643).\n\n\u003c!-- Local Variables: --\u003e\n\u003c!-- indent-tabs-mode: nil --\u003e\n\u003c!-- End: --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocq-community%2Fdocker-coq-action","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frocq-community%2Fdocker-coq-action","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocq-community%2Fdocker-coq-action/lists"}