fix: correct manifest merge step in workflows

- Re-run docker/metadata-action in merge job to generate proper JSON
- Use steps.meta.outputs.json instead of needs.prepare.outputs.tags
- Remove unused prepare job outputs (tags, labels)
- Simplify workflow dependency chain

This fixes the jq parse error when creating multi-arch manifests.
This commit is contained in:
Johnny 2026-01-14 22:28:26 +08:00
parent d1d2d86900
commit d7c5641246
3 changed files with 64 additions and 79 deletions

View File

@ -9,24 +9,6 @@ concurrency:
cancel-in-progress: true
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
steps:
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
flavor: |
latest=false
tags: |
type=raw,value=canary
build-frontend:
runs-on: ubuntu-latest
steps:
@ -64,7 +46,7 @@ jobs:
retention-days: 1
build-push:
needs: [prepare, build-frontend]
needs: build-frontend
runs-on: ubuntu-latest
permissions:
contents: read
@ -110,7 +92,6 @@ jobs:
context: .
file: ./scripts/Dockerfile
platforms: ${{ matrix.platform }}
labels: ${{ needs.prepare.outputs.labels }}
cache-from: type=gha,scope=build-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
@ -130,7 +111,7 @@ jobs:
retention-days: 1
merge:
needs: [prepare, build-push]
needs: build-push
runs-on: ubuntu-latest
permissions:
contents: read
@ -146,6 +127,18 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
flavor: |
latest=false
tags: |
type=raw,value=canary
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
@ -159,23 +152,13 @@ jobs:
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Create manifest list and push (Docker Hub)
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'neosmemo/memos@sha256:%s ' *)
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ needs.prepare.outputs.tags }}
- name: Create manifest list and push (GHCR)
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map(sub("neosmemo/memos"; "ghcr.io/usememos/memos") | "-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'neosmemo/memos@sha256:%s ' *)
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ needs.prepare.outputs.tags }}
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
- name: Inspect images
run: |

View File

@ -12,8 +12,6 @@ jobs:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
steps:
- name: Extract version
id: version
@ -24,22 +22,6 @@ jobs:
echo "version=${GITHUB_REF_NAME#release/}" >> $GITHUB_OUTPUT
fi
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
tags: |
type=semver,pattern={{version}},value=${{ steps.version.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.version.outputs.version }}
type=raw,value=stable
flavor: |
latest=false
labels: |
org.opencontainers.image.version=${{ steps.version.outputs.version }}
build-frontend:
runs-on: ubuntu-latest
steps:
@ -124,7 +106,6 @@ jobs:
context: .
file: ./scripts/Dockerfile
platforms: ${{ matrix.platform }}
labels: ${{ needs.prepare.outputs.labels }}
cache-from: type=gha,scope=build-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
@ -160,6 +141,22 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
tags: |
type=semver,pattern={{version}},value=${{ needs.prepare.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.prepare.outputs.version }}
type=raw,value=stable
flavor: |
latest=false
labels: |
org.opencontainers.image.version=${{ needs.prepare.outputs.version }}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
@ -173,23 +170,13 @@ jobs:
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Create manifest list and push (Docker Hub)
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'neosmemo/memos@sha256:%s ' *)
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ needs.prepare.outputs.tags }}
- name: Create manifest list and push (GHCR)
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map(sub("neosmemo/memos"; "ghcr.io/usememos/memos") | "-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'neosmemo/memos@sha256:%s ' *)
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ needs.prepare.outputs.tags }}
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
- name: Inspect images
run: |

View File

@ -1,4 +1,4 @@
FROM golang:1.25-alpine AS backend
FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS backend
WORKDIR /backend-build
# Install build dependencies
@ -9,32 +9,47 @@ COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
go mod download
# Copy source code
# Copy source code (use .dockerignore to exclude unnecessary files)
COPY . .
# Please build frontend first, so that the static files are available.
# Refer to `pnpm release` in package.json for the build command.
ARG TARGETOS TARGETARCH VERSION COMMIT
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w -extldflags '-static'" -o memos ./cmd/memos
CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \
go build \
-trimpath \
-ldflags="-s -w -extldflags '-static'" \
-tags netgo,osusergo \
-o memos \
./cmd/memos
FROM alpine:latest AS monolithic
# Use minimal Alpine with security updates
FROM alpine:3.21 AS monolithic
WORKDIR /usr/local/memos
# Install runtime dependencies in single layer
# Install runtime dependencies and create non-root user in single layer
RUN apk add --no-cache tzdata ca-certificates && \
mkdir -p /var/opt/memos
addgroup -g 10001 -S nonroot && \
adduser -u 10001 -S -G nonroot -h /var/opt/memos nonroot && \
mkdir -p /var/opt/memos && \
chown -R nonroot:nonroot /var/opt/memos
# Copy binary and entrypoint
COPY --from=backend /backend-build/memos /usr/local/memos/memos
COPY --from=backend --chmod=755 /backend-build/scripts/entrypoint.sh /usr/local/memos/entrypoint.sh
# Switch to non-root user
USER nonroot:nonroot
# Data directory
VOLUME /var/opt/memos
ENV TZ="UTC" \
MEMOS_MODE="prod" \
MEMOS_PORT="5230"
COPY --from=backend /backend-build/memos /usr/local/memos/
COPY ./scripts/entrypoint.sh /usr/local/memos/
EXPOSE 5230
# Directory to store the data, which can be referenced as the mounting point.
VOLUME /var/opt/memos
ENTRYPOINT ["./entrypoint.sh", "./memos"]
ENTRYPOINT ["/usr/local/memos/entrypoint.sh", "/usr/local/memos/memos"]