Skip to content


Browse files Browse the repository at this point in the history
feat(release.yml): Add a (3 jobs)-based GHA using release-please (#434)
* Use var `OPAM_RELEASE` (GitHub PAC)

* Use `expect` to workaround the fact that the feature wish
  is not yet available.

Co-Authored-By: Yann Régis-Gianas <>
Co-Authored-By: Erik Martin-Dorel <>
  • Loading branch information
3 people committed Oct 5, 2021
1 parent dce8f00 commit 7e389ef
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 0 deletions.
121 changes: 121 additions & 0 deletions .github/workflows/release.yml
@@ -0,0 +1,121 @@
name: Release
# Credits: workflow inspired from
# then slightly adapted, using:
# -
# -
# -
# -
# -
# -
workflows: ["Generate static binaries"]
branches: ["master"]
types: ["completed"]
# TODO: dispatch?

name: Create Release
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
release_created: ${{ steps.release.outputs.release_created }}
upload_url: ${{ steps.release.outputs.upload_url }}
tag_name: ${{ steps.release.outputs.tag_name }}
body: ${{ steps.release.outputs.body }}
- uses: GoogleCloudPlatform/release-please-action@v2
id: release
token: ${{ secrets.GITHUB_TOKEN }}
release-type: ocaml
package-name: learn-ocaml
bump-minor-pre-major: true

needs: [release-please]
if: ${{ needs.release-please.outputs.release_created }}
name: Add archive and binaries to release
runs-on: ubuntu-latest
- name: Check out the repo
# Mandatory step (otherwise, hub raises "fatal: Not a git repository")
uses: actions/checkout@v2
- name: Download workflow artifacts
# cf.
uses: dawidd6/action-download-artifact@v2
workflow: static-builds.yml
workflow_conclusion: success
commit: ${{ github.sha }}
path: artifacts
- name: Unpack workflow artifacts
run: |
cd artifacts
mkdir -v target
dist=(linux darwin)
artifact() { printf "learn-ocaml-%s-x86_64.tar.gz" "$d"; }
for d in "${dist[@]}"; do
mkdir -v -- "$d"
( cd "$d" && tar xvzf "../$(artifact "$d")/$(artifact "$d")" )
bin=(./learn-ocaml-client ./learn-ocaml-server ./learn-ocaml)
for b in "${bin[@]}"; do
mv -v -- "$d/$b" "target/$b-$d-x86_64"
- name: Add binaries to release
hub release edit $(find artifacts/target -type f -printf "-a %p ") -m "" "${{ needs.release-please.outputs.tag_name }}"

needs: [release-please]
if: ${{ needs.release-please.outputs.release_created }}
name: Publish to opam registry
# Can be changed for debugging
source_repo: "ocaml-sf/learn-ocaml"
opam_repo: "ocaml/opam-repository"
runs-on: ubuntu-latest
- name: Check out the repo
uses: actions/checkout@v2
- name: Setup bot user
run: |
git config --global ""
git config --global "Learn-OCaml Bot"
# Some hacks to make sure opam doesn't pull the repo in a way we can't deal with
- name: Setup opam repository
run: |
mkdir -v -p ~/.opam/plugins/opam-publish/repos/
git clone git://$opam_repo ~/.opam/plugins/opam-publish/repos/${opam_repo/\//%}
cd ~/.opam/plugins/opam-publish/repos/${opam_repo/\//%}
git remote add user https://${{ secrets.OPAM_RELEASE }}
# Set up our token because opam doesn't support env var tokens
- name: Setup token
run: |
mkdir -p ~/.opam/plugins/opam-publish/
echo -n ${{ secrets.OPAM_RELEASE }} > ~/.opam/plugins/opam-publish/proofbot.token
- name: Generate CHANGES file
CHANGES: ${{ needs.release-please.outputs.body }}
run: |
printf "%s" "$CHANGES" >
# TODO: Docker-based caching
- name: Setup OCaml
uses: avsm/setup-ocaml@v1
ocaml-version: 4.12.0
- name: Install opam-publish
run: |
opam install -y -j 2 opam-publish
- name: Install expect
run: |
sudo apt-get update -y -q
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -q --no-install-recommends expect
- name: Publish to opam
run: |
./scripts/opam-publish.exp "${{ needs.release-please.outputs.tag_name }}" "$opam_repo" "$source_repo"
57 changes: 57 additions & 0 deletions scripts/opam-publish.exp
@@ -0,0 +1,57 @@
#!/usr/bin/expect -f

set tag_name [lindex $argv 0]
set opam_repo [lindex $argv 1]
set source_repo [lindex $argv 2]

# This Expect script was generated by autoexpect on Tue Oct 5 17:03:15 2021
# then modified by Erik Martin-Dorel
# Expect and autoexpect were both written by Don Libes, NIST.
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg

# 2) differing output - Some programs produce different output each time
# they run. The "date" command is an obvious example. Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer. If this causes a problem, delete these patterns or replace
# them with wildcards. An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt). The -P flag allows you to define a character to
# toggle this mode off and on.
# Read the man page for more info.
# -Don

set timeout -1
spawn bash -c {export GIT_PAGER=cat && opam publish --no-browser --tag "$1" --repo="$2" "$3"} bash "$tag_name" "$opam_repo" "$source_repo"
match_max 100000
expect -exact "Please confirm the above data. Continue ? \[Y/n\] "
send -- "y"
expect -exact "File a pull-request for this patch ? \[Y/n\] "
send -- "y"
expect eof

0 comments on commit 7e389ef

Please sign in to comment.