fix: Correct executable bit permissions on binary releases

Due to [an issue][1] with the `actions/upload-artifact` action, when
binaries are uploaded they lose permission bits and `xattr` properties.
Composite actions `upload-tar` and `download-tar` have been added that
tarball the artifacts before uploading them to retain those properties.

[1]: https://github.com/actions/upload-artifact/issues/38
snyk
Robert Dailey 1 year ago
parent df07f7ddf6
commit e1f1872cb7

@ -0,0 +1,25 @@
# This custom action exists because of this issue:
# https://github.com/actions/upload-artifact/issues/38
name: Download Tar Artifact
description: >
Download and extract a tar artifact that was previously uploaded in the workflow by the upload-tar
action
inputs:
name:
description: Artifact name
path:
description: Destination path
required: false
runs:
using: composite
steps:
- uses: actions/download-artifact@v3
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}
- run: ${{ github.action_path }}/untar.sh "${{ inputs.name }}"
working-directory: ${{ inputs.path }}
shell: bash

@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -x
name="$1"
if [[ "$name" == '' ]]; then
dirs=(*/)
else
dirs=(.)
fi
for dir in ${dirs[@]}; do
echo "> Extracting: $dir"
pushd "$dir" > /dev/null
tar xvf artifact.tar
rm artifact.tar
popd > /dev/null
done

@ -0,0 +1,28 @@
# This custom action exists because of this issue:
# https://github.com/actions/upload-artifact/issues/38
name: Upload Tar Artifact
description: Compress files with tar prior to artifacting to keep file privileges.
inputs:
name:
description: Artifact name
path:
description: A directory path. The contents of that directory will be tarballed and uploaded.
required: true
runs:
using: composite
steps:
- run: tar cvf artifact.tar *
shell: bash
working-directory: ${{ inputs.path }}
- uses: actions/upload-artifact@v3
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}/artifact.tar
- run: rm artifact.tar
shell: bash
working-directory: ${{ inputs.path }}

@ -21,6 +21,7 @@ on:
- "ci/**" - "ci/**"
jobs: jobs:
#############################################
build-win: build-win:
name: Build Windows name: Build Windows
secrets: inherit secrets: inherit
@ -32,6 +33,7 @@ jobs:
platform: windows-latest platform: windows-latest
runtime: ${{ matrix.runtime }} runtime: ${{ matrix.runtime }}
#############################################
build-linux: build-linux:
name: Build Linux name: Build Linux
secrets: inherit secrets: inherit
@ -43,6 +45,7 @@ jobs:
platform: ubuntu-latest platform: ubuntu-latest
runtime: ${{ matrix.runtime }} runtime: ${{ matrix.runtime }}
#############################################
build-osx: build-osx:
name: Build Mac OS name: Build Mac OS
secrets: inherit secrets: inherit
@ -57,6 +60,7 @@ jobs:
# https://github.com/dotnet/runtime/issues/79267 # https://github.com/dotnet/runtime/issues/79267
publish-args: -NoCompress publish-args: -NoCompress
#############################################
build-musl: build-musl:
name: Build MUSL name: Build MUSL
secrets: inherit secrets: inherit
@ -70,6 +74,7 @@ jobs:
publish-args: -NoSingleFile publish-args: -NoSingleFile
skip-test: true skip-test: true
#############################################
codesign: codesign:
name: Apple Signing name: Apple Signing
runs-on: macos-latest runs-on: macos-latest
@ -85,7 +90,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Download Artifacts - name: Download Artifacts
uses: actions/download-artifact@v3 uses: ./.github/actions/download-tar
with: with:
name: ${{ matrix.runtime }} name: ${{ matrix.runtime }}
path: publish path: publish
@ -120,17 +125,19 @@ jobs:
# run: xcrun stapler staple -v publish/recyclarr # run: xcrun stapler staple -v publish/recyclarr
- name: Upload Artifacts - name: Upload Artifacts
uses: actions/upload-artifact@v3 uses: ./.github/actions/upload-tar
with: with:
name: ${{ matrix.runtime }} name: ${{ matrix.runtime }}
path: publish/* path: publish
#############################################
docker: docker:
name: Docker name: Docker
needs: [build-musl] needs: [build-musl]
uses: ./.github/workflows/reusable-docker.yml uses: ./.github/workflows/reusable-docker.yml
secrets: inherit secrets: inherit
#############################################
release: release:
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -158,7 +165,7 @@ jobs:
id: gitversion id: gitversion
- name: Download Artifacts - name: Download Artifacts
uses: actions/download-artifact@v3 uses: ./.github/actions/download-tar
with: with:
path: publish path: publish
@ -178,12 +185,15 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.DEPLOY_PAT }} GITHUB_TOKEN: ${{ secrets.DEPLOY_PAT }}
with: with:
files: archive/* files: |
archive/**/recyclarr-*.zip
archive/**/recyclarr-*.tar.xz
body: ${{ steps.changelog.outputs.release_notes }} body: ${{ steps.changelog.outputs.release_notes }}
tag_name: ${{ github.event.create.ref }} tag_name: ${{ github.event.create.ref }}
draft: false draft: false
prerelease: ${{ steps.gitversion.outputs.preReleaseTag != '' }} prerelease: ${{ steps.gitversion.outputs.preReleaseTag != '' }}
#############################################
# The main purpose of this job is to group all the other jobs together into one single job status # The main purpose of this job is to group all the other jobs together into one single job status
# that can be set as a requirement to merge pull requests. This is easier than enumerating all # that can be set as a requirement to merge pull requests. This is easier than enumerating all
# jobs in a workflow to ensure they all pass. # jobs in a workflow to ensure they all pass.

@ -39,16 +39,15 @@ jobs:
- name: Publish - name: Publish
shell: pwsh shell: pwsh
run: | run: ci/Publish.ps1 -Runtime ${{ inputs.runtime }} ${{ inputs.publish-args }}
ci/Publish.ps1 -Runtime ${{ inputs.runtime }} ${{ inputs.publish-args }}
- name: Smoke - name: Smoke
if: endsWith(inputs.runtime, 'x64') && !inputs.skip-test if: endsWith(inputs.runtime, 'x64') && !inputs.skip-test
shell: pwsh shell: pwsh
run: ci/SmokeTest.ps1 publish/${{ inputs.runtime }}/recyclarr run: ci/SmokeTest.ps1 publish/${{ inputs.runtime }}/recyclarr
- name: Upload Artifacts - name: Upload Artifact
uses: actions/upload-artifact@v3 uses: ./.github/actions/upload-tar
with: with:
name: ${{ inputs.runtime }} name: ${{ inputs.runtime }}
path: publish/${{ inputs.runtime }}/* path: publish/${{ inputs.runtime }}

@ -45,7 +45,7 @@ jobs:
${{ env.SEMVER }},pattern={{major}} ${{ env.SEMVER }},pattern={{major}}
- name: Grab Artifacts - name: Grab Artifacts
uses: actions/download-artifact@v3 uses: ./.github/actions/download-tar
with: with:
path: docker/artifacts path: docker/artifacts

@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Fixed
- Releases now retain executable permissions on Linux and macOS.
## [4.0.1] - 2022-12-21 ## [4.0.1] - 2022-12-21
### Changed ### Changed

@ -1,7 +1,7 @@
[CmdletBinding()] [CmdletBinding()]
param ( param (
[string[]] $RunArgs, [string] $Runtime = "linux-musl-x64",
[string] $Runtime = "linux-musl-x64" [string[]] $RunArgs
) )
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"

@ -1,17 +1,15 @@
FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS build FROM mcr.microsoft.com/dotnet/runtime:7.0-alpine as base
WORKDIR /build FROM base AS base-arm
ENV RUNTIME=linux-musl-arm
ARG TARGETPLATFORM FROM base AS base-arm64
ENV RUNTIME=linux-musl-arm64
RUN apk add unzip bash FROM base AS base-amd64
ENV RUNTIME=linux-musl-x64
COPY --chmod=544 ./scripts/build/*.sh . FROM base-$TARGETARCH AS final
COPY ./artifacts ./artifacts
RUN ./build.sh
#############################################################################
FROM mcr.microsoft.com/dotnet/runtime:7.0-alpine AS final
# Required by environment and/or dotnet # Required by environment and/or dotnet
ENV PATH="${PATH}:/app/recyclarr" \ ENV PATH="${PATH}:/app/recyclarr" \
@ -23,7 +21,7 @@ RUN set -ex; \
apk add --no-cache bash tzdata supercronic git tini; \ apk add --no-cache bash tzdata supercronic git tini; \
mkdir -p /config && chown 1000:1000 /config; mkdir -p /config && chown 1000:1000 /config;
COPY --from=build /build/publish /app/recyclarr/ COPY ./artifacts/$RUNTIME /app/recyclarr/
COPY --chmod=555 ./scripts/prod/*.sh / COPY --chmod=555 ./scripts/prod/*.sh /
USER 1000:1000 USER 1000:1000

@ -10,7 +10,7 @@ services:
build: build:
context: . context: .
args: args:
- TARGETPLATFORM=linux/amd64 - TARGETARCH=amd64
networks: [recyclarr] networks: [recyclarr]
volumes: volumes:
- ./config:/config - ./config:/config

@ -1,16 +0,0 @@
#!/usr/bin/env bash
set -ex
# Determine the runtime from the target platform provided by Docker Buildx
case "$TARGETPLATFORM" in
"linux/arm/v7") runtime="linux-musl-arm" ;;
"linux/arm64") runtime="linux-musl-arm64" ;;
"linux/amd64") runtime="linux-musl-x64" ;;
*) echo >&2 "ERROR: Unsupported target platform: $TARGETPLATFORM"; exit 1 ;;
esac
path="artifacts/$runtime/"
mv "$path" publish
chmod a+rx publish/recyclarr
Loading…
Cancel
Save