mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-07 21:44:02 -05:00
ci: harden release pipeline; gate to upstream, migrate tokens, remove docker-on-tag
CHANGES - Gate release and version workflows to upstream owner only. - Switch tagging and releases to built-in GITHUB_TOKEN. - Replace environment passing with step outputs across workflows. - Remove docker-publish-on-tag workflow to reduce duplication and complexity. - Add OCI description label to Docker image. - Document GHCR multi-arch annotations for accurate package descriptions. - Update README with new ARM binary release announcement. - Simplify GoReleaser config by removing comments and extras.
This commit is contained in:
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@@ -1,9 +1,12 @@
|
||||
## What this Pull Request (PR) does
|
||||
|
||||
Please briefly describe what this PR does.
|
||||
|
||||
## Related issues
|
||||
|
||||
Please reference any open issues this PR relates to in here.
|
||||
If it closes an issue, type `closes #[ISSUE_NUMBER]`.
|
||||
|
||||
## Screenshots
|
||||
|
||||
Provide any screenshots you may find relevant to facilitate us understanding your PR.
|
||||
|
||||
150
.github/workflows/docker-publish-on-tag.yml
vendored
150
.github/workflows/docker-publish-on-tag.yml
vendored
@@ -1,150 +0,0 @@
|
||||
name: Release Docker image on tag (GHCR + Docker Hub)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"] # e.g., v1.4.300
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write # needed for GHCR with GITHUB_TOKEN
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
# Optional safety: only run from your fork
|
||||
if: ${{ github.repository_owner == 'ksylvan' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
is_latest: ${{ steps.latest.outputs.is_latest }}
|
||||
owner_lc: ${{ steps.vars.outputs.owner_lc }}
|
||||
repo_lc: ${{ steps.vars.outputs.repo_lc }}
|
||||
dockerhub_user_lc: ${{ steps.dh.outputs.user_lc }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # full history for tag comparisons
|
||||
|
||||
- name: Fetch all tags
|
||||
run: git fetch --tags --force
|
||||
|
||||
# More reliable cross-builds
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Compute lowercase owner/repo for registry image names
|
||||
- name: Compute image names
|
||||
id: vars
|
||||
run: |
|
||||
OWNER="${GITHUB_REPOSITORY_OWNER}"
|
||||
REPO="${GITHUB_REPOSITORY#*/}"
|
||||
echo "owner_lc=${OWNER,,}" >> "$GITHUB_OUTPUT"
|
||||
echo "repo_lc=${REPO,,}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Lowercase Docker Hub username (belt & suspenders)
|
||||
- name: Lowercase Docker Hub username
|
||||
id: dh
|
||||
run: echo "user_lc=${DOCKERHUB_USERNAME,,}" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
|
||||
# Determine if the current tag is the highest vX.Y.Z (no pre-releases)
|
||||
- name: Is this the latest semver tag?
|
||||
id: latest
|
||||
shell: bash
|
||||
run: |
|
||||
CTAG="${GITHUB_REF_NAME}"
|
||||
LATEST="$(git tag -l 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n1)"
|
||||
echo "current_tag=$CTAG" >> "$GITHUB_OUTPUT"
|
||||
echo "latest_tag=$LATEST" >> "$GITHUB_OUTPUT"
|
||||
if [[ "$CTAG" == "$LATEST" ]]; then
|
||||
echo "is_latest=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "is_latest=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Login to GHCR (uses built-in GITHUB_TOKEN)
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ steps.dh.outputs.user_lc }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Generate versioned tags/labels for BOTH registries (no :latest here)
|
||||
- name: Extract metadata (tags, labels)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/${{ steps.vars.outputs.owner_lc }}/${{ steps.vars.outputs.repo_lc }}
|
||||
docker.io/${{ steps.dh.outputs.user_lc }}/${{ steps.vars.outputs.repo_lc }}
|
||||
tags: |
|
||||
type=ref,event=tag # v1.4.300
|
||||
type=semver,pattern={{version}} # 1.4.300 (optional)
|
||||
type=semver,pattern={{major}}.{{minor}} # 1.4 (optional)
|
||||
labels: |
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
|
||||
- name: Build and push (multi-arch)
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./scripts/docker/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
# Separate job to (re)point :latest — serialized to avoid races
|
||||
move-latest:
|
||||
needs: build-and-push
|
||||
if: ${{ needs.build-and-push.outputs.is_latest == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Only one "latest" move at a time; newer runs cancel older in-progress ones
|
||||
concurrency:
|
||||
group: latest-${{ github.repository }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Tag :latest on GHCR
|
||||
run: |
|
||||
SRC="ghcr.io/${{ needs.build-and-push.outputs.owner_lc }}/${{ needs.build-and-push.outputs.repo_lc }}:${{ github.ref_name }}"
|
||||
DST="ghcr.io/${{ needs.build-and-push.outputs.owner_lc }}/${{ needs.build-and-push.outputs.repo_lc }}:latest"
|
||||
docker buildx imagetools create -t "$DST" "$SRC"
|
||||
|
||||
- name: Tag :latest on Docker Hub
|
||||
run: |
|
||||
SRC="docker.io/${{ needs.build-and-push.outputs.dockerhub_user_lc }}/${{ needs.build-and-push.outputs.repo_lc }}:${{ github.ref_name }}"
|
||||
DST="docker.io/${{ needs.build-and-push.outputs.dockerhub_user_lc }}/${{ needs.build-and-push.outputs.repo_lc }}:latest"
|
||||
docker buildx imagetools create -t "$DST" "$SRC"
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -28,6 +28,8 @@ jobs:
|
||||
run: go test -v ./...
|
||||
|
||||
build:
|
||||
# only run in main upstream repo
|
||||
if: ${{ github.repository_owner == 'danielmiessler' }}
|
||||
name: Build & Release with Goreleaser
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
@@ -48,4 +50,4 @@ jobs:
|
||||
distribution: goreleaser
|
||||
args: release --clean
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets._GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -21,9 +21,10 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
update-version:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
if: >
|
||||
${{ github.repository_owner == 'danielmiessler' }} &&
|
||||
github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
@@ -48,12 +49,13 @@ jobs:
|
||||
run: |
|
||||
latest_tag=$(git tag --sort=-creatordate | head -n 1)
|
||||
echo "Latest tag is: $latest_tag"
|
||||
echo "tag=$latest_tag" >> $GITHUB_OUTPUT
|
||||
echo "tag=$latest_tag" >> $GITHUB_ENV # Save the latest tag to environment file
|
||||
|
||||
- name: Increment patch version
|
||||
id: increment_version
|
||||
run: |
|
||||
latest_tag=${{ env.tag }}
|
||||
latest_tag=${{ steps.get_latest_tag.outputs.tag }}
|
||||
major=$(echo "$latest_tag" | cut -d. -f1 | sed 's/v//')
|
||||
minor=$(echo "$latest_tag" | cut -d. -f2)
|
||||
patch=$(echo "$latest_tag" | cut -d. -f3)
|
||||
@@ -61,19 +63,21 @@ jobs:
|
||||
new_version="${major}.${minor}.${new_patch}"
|
||||
new_tag="v${new_version}"
|
||||
echo "New version is: $new_version"
|
||||
echo "new_version=$new_version" >> $GITHUB_OUTPUT
|
||||
echo "new_version=$new_version" >> $GITHUB_ENV # Save the new version to environment file
|
||||
echo "New tag is: $new_tag"
|
||||
echo "new_tag=$new_tag" >> $GITHUB_OUTPUT
|
||||
echo "new_tag=$new_tag" >> $GITHUB_ENV # Save the new tag to environment file
|
||||
|
||||
- name: Update version.go file
|
||||
run: |
|
||||
echo "package main" > cmd/fabric/version.go
|
||||
echo "" >> cmd/fabric/version.go
|
||||
echo "var version = \"${{ env.new_tag }}\"" >> cmd/fabric/version.go
|
||||
echo "var version = \"${{ steps.increment_version.outputs.new_tag }}\"" >> cmd/fabric/version.go
|
||||
|
||||
- name: Update version.nix file
|
||||
run: |
|
||||
echo "\"${{ env.new_version }}\"" > nix/pkgs/fabric/version.nix
|
||||
echo "\"${{ steps.increment_version.outputs.new_version }}\"" > nix/pkgs/fabric/version.nix
|
||||
|
||||
- name: Format source code
|
||||
run: |
|
||||
@@ -87,7 +91,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
go run ./cmd/generate_changelog --process-prs ${{ env.new_tag }}
|
||||
go run ./cmd/generate_changelog --process-prs ${{ steps.increment_version.outputs.new_tag }}
|
||||
go run ./cmd/generate_changelog --sync-db
|
||||
- name: Commit changes
|
||||
run: |
|
||||
@@ -100,7 +104,7 @@ jobs:
|
||||
# and removing the incoming/ directory.
|
||||
|
||||
if ! git diff --staged --quiet; then
|
||||
git commit -m "chore(release): Update version to ${{ env.new_tag }}"
|
||||
git commit -m "chore(release): Update version to ${{ steps.increment_version.outputs.new_tag }}"
|
||||
else
|
||||
echo "No changes to commit."
|
||||
fi
|
||||
@@ -113,10 +117,10 @@ jobs:
|
||||
|
||||
- name: Create a new tag
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.TAG_PAT }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
git tag ${{ env.new_tag }}
|
||||
git push origin ${{ env.new_tag }} # Push the new tag
|
||||
git tag ${{ steps.increment_version.outputs.new_tag }}
|
||||
git push origin ${{ steps.increment_version.outputs.new_tag }} # Push the new tag
|
||||
|
||||
- name: Dispatch event to trigger release workflow
|
||||
env:
|
||||
@@ -126,4 +130,4 @@ jobs:
|
||||
-H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
https://api.github.com/repos/${{ github.repository }}/dispatches \
|
||||
-d '{"event_type": "tag_created", "client_payload": {"tag": "${{ env.new_tag }}"}}'
|
||||
-d '{"event_type": "tag_created", "client_payload": {"tag": "${{ steps.increment_version.outputs.new_tag }}"}}'
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||
# Make sure to check the documentation at https://goreleaser.com
|
||||
|
||||
# The lines below are called `modelines`. See `:help modeline`
|
||||
# Feel free to remove those if you don't want/need to use them.
|
||||
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
|
||||
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
|
||||
# Read the documentation at https://goreleaser.com
|
||||
|
||||
version: 2
|
||||
|
||||
@@ -26,7 +20,6 @@ builds:
|
||||
main: ./cmd/fabric
|
||||
binary: fabric
|
||||
|
||||
|
||||
archives:
|
||||
- formats: [tar.gz]
|
||||
# this name template makes the OS and Arch compatible with the results of `uname`.
|
||||
@@ -41,36 +34,3 @@ archives:
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
formats: [zip]
|
||||
|
||||
winget:
|
||||
- name: Fabric
|
||||
publisher: danielmiessler
|
||||
license: MIT
|
||||
homepage: https://github.com/danielmiessler/fabric
|
||||
copyright: Daniel Miessler
|
||||
short_description: open-source AI framework for augmenting
|
||||
repository:
|
||||
owner: danielmiessler
|
||||
name: winget-pkgs
|
||||
branch: "danielmiessler.Fabric-{{.Version}}"
|
||||
pull_request:
|
||||
enabled: true
|
||||
draft: true
|
||||
base:
|
||||
owner: microsoft
|
||||
name: winget-pkgs
|
||||
branch: master
|
||||
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- "^docs:"
|
||||
- "^test:"
|
||||
|
||||
release:
|
||||
footer: >-
|
||||
|
||||
---
|
||||
|
||||
Released by [GoReleaser](https://github.com/goreleaser/goreleaser).
|
||||
|
||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -65,6 +65,7 @@
|
||||
"goopenai",
|
||||
"GOPATH",
|
||||
"gopkg",
|
||||
"Goreleaser",
|
||||
"GOROOT",
|
||||
"Graphviz",
|
||||
"grokai",
|
||||
@@ -105,6 +106,8 @@
|
||||
"mbed",
|
||||
"metacharacters",
|
||||
"Miessler",
|
||||
"modeline",
|
||||
"modelines",
|
||||
"mpga",
|
||||
"nometa",
|
||||
"numpy",
|
||||
@@ -162,6 +165,7 @@
|
||||
"videoid",
|
||||
"webp",
|
||||
"WEBVTT",
|
||||
"winget",
|
||||
"wipecontext",
|
||||
"wipesession",
|
||||
"wireframes",
|
||||
|
||||
@@ -57,6 +57,7 @@ Below are the **new features and capabilities** we've added (newest first):
|
||||
|
||||
### Recent Major Features
|
||||
|
||||
- [v1.4.303](https://github.com/danielmiessler/fabric/releases/tag/v1.4.303) (Aug 29, 2025) — **New Binary Releases**: Linux ARM and Windows ARM targets. You can run Fabric on the Raspberry PI and on your Windows Surface!
|
||||
- [v1.4.294](https://github.com/danielmiessler/fabric/releases/tag/v1.4.294) (Aug 20, 2025) — **Venice AI Support**: Added the Venice AI provider. Venice is a Privacy-First, Open-Source AI provider. See their ["About Venice"](https://docs.venice.ai/overview/about-venice) page for details.
|
||||
- [v1.4.291](https://github.com/danielmiessler/fabric/releases/tag/v1.4.291) (Aug 18, 2025) — **Speech To Text**: Add OpenAI speech-to-text support with `--transcribe-file`, `--transcribe-model`, and `--split-media-file` flags.
|
||||
- [v1.4.287](https://github.com/danielmiessler/fabric/releases/tag/v1.4.287) (Aug 16, 2025) — **AI Reasoning**: Add Thinking to Gemini models and introduce `readme_updates` python script
|
||||
|
||||
8
cmd/generate_changelog/incoming/1736.txt
Normal file
8
cmd/generate_changelog/incoming/1736.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
### PR [#1736](https://github.com/danielmiessler/Fabric/pull/1736) by [tonymet](https://github.com/tonymet): Winget Publishing and GoReleaser
|
||||
|
||||
- Added GoReleaser support for improved package distribution
|
||||
- Winget and Docker publishing moved to ksylvan/fabric-packager GitHub repo
|
||||
- Hardened release pipeline by gating workflows to upstream owner only
|
||||
- Migrated from custom tokens to built-in GITHUB_TOKEN for enhanced security
|
||||
- Removed docker-publish-on-tag workflow to reduce duplication and complexity
|
||||
- Added ARM binary release support with updated documentation
|
||||
@@ -16,6 +16,8 @@ RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /fabric ./cmd/fabric
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
LABEL org.opencontainers.image.description="A Docker image for running the Fabric CLI. See https://github.com/danielmiessler/Fabric/tree/main/scripts/docker for details."
|
||||
|
||||
RUN apk add --no-cache ca-certificates \
|
||||
&& mkdir -p /root/.config/fabric
|
||||
|
||||
|
||||
@@ -46,3 +46,15 @@ docker run --rm -it -p 8080:8080 -v $HOME/.fabric-config:/root/.config/fabric fa
|
||||
```
|
||||
|
||||
The API will be available at `http://localhost:8080`.
|
||||
|
||||
## Multi-arch builds and GHCR packages
|
||||
|
||||
For multi-arch Docker builds (such as those used for GitHub Container Registry packages), the description should be set via annotations in the manifest instead of the Dockerfile LABEL. When building multi-arch images, ensure the build configuration includes:
|
||||
|
||||
```json
|
||||
"annotations": {
|
||||
"org.opencontainers.image.description": "A Docker image for running the Fabric CLI. See https://github.com/danielmiessler/Fabric/tree/main/scripts/docker for details."
|
||||
}
|
||||
```
|
||||
|
||||
This ensures that GHCR packages display the proper description.
|
||||
|
||||
Reference in New Issue
Block a user