Ir al contenido

macOS

El mismo binario estático que en todas partes, compilado para darwin tanto en Apple silicon como en Intel. macOS no es una plataforma que solo se compile y se dé por buena: cada cambio ejecuta la suite unitaria entera y la suite de extremo a extremo en un runner de macOS, junto a Linux y Windows.

Los archivos de release dicen darwin, que es el nombre que la cadena de herramientas de Go da al sistema; macOS es el nombre que le da Apple. uname -m dice qué arquitectura es.

Lo que dice uname -mLa máquinaEl archivo que toca
arm64Apple silicondarwin_arm64
x86_64Inteldarwin_amd64
Ventana de terminal
VERSION=1.0.0
arch=$(uname -m); case "$arch" in x86_64) arch=amd64 ;; esac
base=https://github.com/jmrplens/ghchronicle/releases/download/v$VERSION
curl -fsSLO "$base/ghchronicle_${VERSION}_darwin_${arch}.tar.gz"

Junto a los archivos se publican dos ficheros: checksums.txt, que lleva el SHA-256 de cada archivo, y checksums.txt.sigstore.json, que es una firma sobre ese fichero.

  1. Coge el fichero de sumas y su firma.

    Ventana de terminal
    curl -fsSLO "$base/checksums.txt"
    curl -fsSLO "$base/checksums.txt.sigstore.json"
  2. Comprueba el archivo contra él. macOS trae shasum y no el sha256sum de una máquina Linux, así que se selecciona la línea de tu archivo y se le pasa por la tubería, que funciona con cualquier versión de shasum.

    Ventana de terminal
    grep "darwin_${arch}.tar.gz$" checksums.txt | shasum -a 256 -c -
    ghchronicle_1.0.0_darwin_arm64.tar.gz: OK
  3. Comprueba el propio fichero de sumas, si tienes cosign.

    Ventana de terminal
    cosign verify-blob \
    --certificate-identity-regexp 'https://github.com/jmrplens/ghchronicle/.github/workflows/release.yml@refs/tags/.*' \
    --certificate-oidc-issuer https://token.actions.githubusercontent.com \
    --bundle checksums.txt.sigstore.json \
    checksums.txt
    Verified OK

La firma es sin claves: la identidad que se verifica es el workflow que se ejecutó, anotado en un registro público de transparencia, y por eso las dos opciones --certificate no son opcionales. Sin ellas cosign confirmaría que alguien firmó el fichero, que no es la pregunta.

El archivo lleva tres ficheros y ningún directorio.

  • Directorioghchronicle_1.0.0_darwin_arm64.tar.gz
    • ghchronicle el binario
    • LICENSE
    • README.md
Ventana de terminal
tar -xzf ghchronicle_1.0.0_darwin_arm64.tar.gz ghchronicle
sudo install -m 755 ghchronicle /usr/local/bin/
ghchronicle -version

/usr/local/bin está en el PATH por omisión de cualquier instalación de macOS, en las dos arquitecturas, porque /etc/paths lo lista el primero.

El binario necesita un fichero de configuración y un token, y el inicio rápido escribe los dos en seis pasos. Con eso hecho:

Ventana de terminal
ghchronicle -config config.yaml -list # qué se recogería
ghchronicle -config config.yaml -once # una pasada y termina

launchd es lo que macOS tiene en vez de systemd, y la primera decisión que te pide es agente o demonio.

Un LaunchAgentUn LaunchDaemon
Vive en~/Library/LaunchAgents//Library/LaunchDaemons/
Corre comoroot, o el UserName que le des
Corre cuandohas iniciado sesiónla máquina está encendida, desde el arranque
Bueno paraun portátil que usasun Mac que se queda encendido

El agente es por donde empezar. No necesita sudo, y un colector que se para mientras el dueño del portátil está fuera de sesión no pierde nada que la siguiente pasada no recoja.

~/Library/LaunchAgents/io.jmrp.ghchronicle.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>io.jmrp.ghchronicle</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/ghchronicle</string>
<string>-config</string>
<string>/Users/tu/Library/Application Support/ghchronicle/config.yaml</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>GITHUB_TOKEN</key>
<string>github_pat_...</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/tu/Library/Logs/ghchronicle.log</string>
<key>StandardErrorPath</key>
<string>/Users/tu/Library/Logs/ghchronicle.log</string>
</dict>
</plist>
  1. Protege el fichero antes de que lleve un token, y luego cárgalo.

    Ventana de terminal
    chmod 600 ~/Library/LaunchAgents/io.jmrp.ghchronicle.plist
    launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/io.jmrp.ghchronicle.plist
  2. Mira que está arriba, y lee lo que dice.

    Ventana de terminal
    launchctl print gui/$(id -u)/io.jmrp.ghchronicle
    tail -f ~/Library/Logs/ghchronicle.log
  3. Después de editar el fichero, descárgalo y vuelve a cargarlo. launchd lee la lista de propiedades una sola vez, al arrancarla.

    Ventana de terminal
    launchctl bootout gui/$(id -u)/io.jmrp.ghchronicle
    launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/io.jmrp.ghchronicle.plist

StartInterval es el cron de launchd, en segundos, y -once es el modo que le va. Sustituye KeepAlive por él y añade -once a ProgramArguments:

<key>StartInterval</key>
<integer>3600</integer>

Deja state_file en una ruta que sobreviva, en este modo sobre todo: es lo que evita que el recorrido completo de estrellas y el relleno año por año del calendario de contribuciones vuelvan a ocurrir en cada ejecución.

Go 1.27.1 o más nuevo es lo que declara el módulo. La compilación fija CGO_ENABLED=0, así que las herramientas de línea de órdenes de Xcode no hacen falta para ella.

Ventana de terminal
go install github.com/jmrplens/ghchronicle/cmd/ghchronicle@latest

Cae en $(go env GOPATH)/bin, que es ~/go/bin salvo que lo hayas movido, y ese directorio tiene que estar en tu PATH. Un binario hecho así informa de su versión pero no de su commit ni de su fecha de compilación, porque esas dos las sella la compilación de release y un módulo descargado por el proxy no lleva copia de trabajo de donde leerlas.

El colector no busca el fichero de configuración en ningún sitio concreto: -config vale por omisión config.yaml relativo al directorio de trabajo, y detrás no hay ninguna ruta de búsqueda. macOS no tiene la costumbre de /etc/ghchronicle, así que estos son los sitios convencionales, no sitios que la herramienta conozca:

FicheroPara un agentePara un demonio
Configuración~/Library/Application Support/ghchronicle//usr/local/etc/ghchronicle/
Estado y registro~/Library/Application Support/ghchronicle//usr/local/var/ghchronicle/
Log~/Library/Logs/ghchronicle.log/usr/local/var/log/

state_file tiene un valor por omisión propio, ghchronicle-state.json en el directorio de trabajo, con el registro de escrituras al lado como ghchronicle-state-written.bin. El directorio de trabajo de un trabajo de launchd no es algo en lo que apoyarse. Ponlo.